diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63f5d2f1b..e1f568bc6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,10 @@ on: # immutable-package release track keyed to module.package.codefly.yaml. tags: ["v*", "module-package/v*"] pull_request: - branches: [main] + # release/** carries a patch line cut from a deploy-counter tag: a pull + # request into one gets the same checks as one into main, or it would merge + # with none. + branches: [main, "release/**"] # The merge queue builds each entry as `main + the PR` and reports the # required checks from THAT ref, which is the guarantee "require branches to # be up to date" was buying by making every author rebase by hand. Every @@ -236,13 +239,18 @@ jobs: # Renders to "false" when the label is absent; the gate requires an # affirmative token, so only the label opens the escape hatch. AUTHZ_ALLOW_BROADENING: ${{ contains(github.event.pull_request.labels.*.name, 'authz-broadening-approved') }} + # The branch the pull request merges into: main, or a release/** patch + # line. Diffing a patch line's pull request against main would report + # everything main gained since the line was cut, or hide a broadening + # main already carries. Outside a pull request it is main, as before. + BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }} run: | - git fetch --no-tags origin refs/heads/main:refs/remotes/origin/main + git fetch --no-tags origin "refs/heads/${BASE_REF}:refs/remotes/origin/${BASE_REF}" base="$(mktemp)" - if git show origin/main:module/services/accounts/generated/authz-methods.json > "${base}" 2>/dev/null; then + if git show "origin/${BASE_REF}:module/services/accounts/generated/authz-methods.json" > "${base}" 2>/dev/null; then node module/tools/authz-coverage-gate.mjs no-broadening --base "${base}" else - echo "no authorization catalog on main yet; nothing to diff" + echo "no authorization catalog on ${BASE_REF} yet; nothing to diff" fi - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: @@ -517,12 +525,26 @@ jobs: # contract once a concurrent change lands is caught where it has to # be: the merge queue builds main + the PR afresh, so there HEAD^1 IS # current main. + # + # A tag whose commit is not on main was cut from a release/** patch + # line. Its baseline is the line's base, where it forked from main + # (the release it patches), not main as it stands: main may have + # gained messages since, which the line lacks and would report as + # deletions. Every tag on main, and every other event, keeps main. if git rev-parse --verify -q HEAD^2 >/dev/null; then baseline_rev="HEAD^1" else git fetch --no-tags origin \ refs/heads/main:refs/remotes/origin/main baseline_rev="origin/main" + if [[ "${GITHUB_REF}" == refs/tags/* ]]; then + if git merge-base --is-ancestor HEAD origin/main; then on_main=0; else on_main=$?; fi + case "${on_main}" in + 0) ;; + 1) baseline_rev="$(git merge-base HEAD origin/main)" ;; + *) echo "::error::cannot tell whether ${GITHUB_REF_NAME} is on main (git exit ${on_main})"; exit 1 ;; + esac + fi fi echo "proto baseline: ${baseline_rev} ($(git rev-parse --short "${baseline_rev}"))" git archive "${baseline_rev}" module/services/accounts/proto | tar -x -C "${baseline}" @@ -1398,10 +1420,40 @@ jobs: timeout-minutes: 5 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + # A tag push names a commit, not a branch, so the branch a tag was cut + # from is not in the event. What decides "current" is whether main + # contains the tagged commit: a tag cut from a release/** patch line is + # not on main, and announcing it would make an interface current that + # lacks whatever main released since. Such a tag still passes every gate + # above; only the announcement waits for main's next tag. + - name: Check the tagged commit is on main + id: on-main + run: | + git fetch --no-tags origin main + # 1 is "not an ancestor"; anything else is git failing to answer, + # which must fail the step rather than read as "not on main". + if git merge-base --is-ancestor "${GITHUB_SHA}" FETCH_HEAD; then on_main=0; else on_main=$?; fi + case "${on_main}" in + 0) + echo "announce=true" >> "${GITHUB_OUTPUT}" + ;; + 1) + echo "::notice::${GITHUB_REF_NAME} is not on main; the release is not announced." + echo "announce=false" >> "${GITHUB_OUTPUT}" + ;; + *) + echo "::error::cannot tell whether ${GITHUB_REF_NAME} is on main (git exit ${on_main})" + exit 1 + ;; + esac - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + if: steps.on-main.outputs.announce == 'true' with: node-version: 24 - name: Dispatch surface-bump + if: steps.on-main.outputs.announce == 'true' env: HANDBOOK_REPOSITORY: ${{ vars.HANDBOOK_REPOSITORY }} GH_TOKEN: ${{ secrets.HANDBOOK_DISPATCH_TOKEN }} diff --git a/RELEASE_GATES.md b/RELEASE_GATES.md index 77740124f..7c2544774 100644 --- a/RELEASE_GATES.md +++ b/RELEASE_GATES.md @@ -148,6 +148,15 @@ With both present, a dispatch the handbook rejects still fails the job. including that an unconfigured run dispatches nothing at all — and runs in `release-contract`. +Only a tag on `main` is announced. A tag push names a commit, not a branch, so +`handbook-surface-bump` first asks whether `main` contains the tagged commit +(`git merge-base --is-ancestor`). A tag cut from a `release/**` patch line is +not on `main`: it passes every gate and publishes every artifact, but it is not +announced as current, because it lacks whatever `main` released after the line +was cut. `main`'s next tag carries the announcement. Exit 1 of that check is +"not on main"; any other failure fails the job rather than skipping the +announcement silently. + ### The contract test `release-contract` runs `scripts/ci/release-gates.mjs check`, which parses every @@ -795,6 +804,18 @@ To cut a deploy-counter tag: 2. Commit it as `release: v0.0.N`. 3. Tag that commit with an annotated `v0.0.N` tag and push the tag. +**Patch lines.** A fix for a deployment pinned to an older deploy-counter tag +goes on a `release/**` branch cut from that tag, through a pull request into +it; pull requests into `release/**` get the same checks as pull requests into +`main`. A tag on the line passes every release gate and publishes its artifacts +like a tag on `main`, with two differences. It is not announced as current +(only a tag on `main` is; see `handbook-surface-bump` above). And the gates that +compare against a baseline compare against the line's base, not against `main` +as it stands: the authorization no-broadening check diffs a pull request +against the branch it merges into, and the protobuf breaking-change check on a +tag that is not on `main` compares against its merge base with `main`, the +release the line patches. + To cut an immutable module-package release: 1. Bump `version:` in `module/module.package.codefly.yaml`. diff --git a/module/services/frontend/code/package-lock.json b/module/services/frontend/code/package-lock.json index b8ba2435b..cb7822b6c 100644 --- a/module/services/frontend/code/package-lock.json +++ b/module/services/frontend/code/package-lock.json @@ -16,8 +16,8 @@ "@codefly-dev/saas-plugin-contract": "2.4.4", "@codefly-dev/saas-plugin-react": "0.4.5", "@codefly-dev/saas-sdk": "0.3.35", - "@codefly-dev/saas-ui": "0.12.8", - "@codefly-dev/ui": "0.12.8", + "@codefly-dev/saas-ui": "0.13.0", + "@codefly-dev/ui": "0.13.0", "@codefly/saas-plugin-manifest": "0.1.2", "@codefly/saas-settings": "0.1.0", "@connectrpc/connect": "^2.1.1", @@ -28,9 +28,9 @@ "@fontsource/newsreader": "^5.3.0", "@fontsource/roboto": "^5.3.0", "@fontsource/source-serif-4": "^5.3.0", - "@hookform/resolvers": "^3.9.0", + "@hookform/resolvers": "^5.9.2", "@module-federation/runtime": "^2.8.2", - "@sentry/nextjs": "^10.50.0", + "@sentry/nextjs": "10.75.2", "@simplewebauthn/browser": "^13.3.0", "@tanstack/react-query": "^5.60.0", "@tanstack/react-table": "^8.21.3", @@ -38,16 +38,16 @@ "codefly": "https://github.com/codefly-dev/sdk-js/archive/9f3bb78682a0c2b9a70631d35c2ae0094c281ac5.tar.gz", "js-yaml": "^4.3.2", "lucide-react": "^1.8.0", - "next": "^16.2.12", + "next": "16.4.1", "react": "^19.2.8", "react-dom": "^19.2.8", - "react-hook-form": "^7.54.0", + "react-hook-form": "^7.55.0", "server-only": "^0.0.1", "sonner": "^2.0.7", "swagger-ui-react": "^5.32.14", "tailwind-merge": "^3.5.0", "tw-animate-css": "^1.4.0", - "zod": "^3.24.0" + "zod": "^4.6.6" }, "devDependencies": { "@biomejs/biome": "^2.5.4", @@ -64,7 +64,7 @@ "ajv": "^8.17.1", "babel-plugin-react-compiler": "1.0.0", "eslint": "^9.39.5", - "eslint-config-next": "^16.2.12", + "eslint-config-next": "16.4.1", "happy-dom": "^20.8.9", "jsdom": "^29.0.2", "msw": "^2.7.0", @@ -1703,12 +1703,113 @@ } }, "node_modules/@hookform/resolvers": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.10.0.tgz", - "integrity": "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.9.2.tgz", + "integrity": "sha512-RtjTnZqsC38s4NKp2XO3fD8IA5uyN4tB7McQ5C6uiMPcV+WWO8F+wVa3e+BXUpH2ScgxghAlwFRMVqjT9WChAQ==", "license": "MIT", + "dependencies": { + "@standard-schema/utils": "^0.3.0" + }, "peerDependencies": { - "react-hook-form": "^7.0.0" + "@sinclair/typebox": ">=0.25.24", + "@standard-schema/spec": "^1.0.0", + "@typeschema/main": ">=0.13.7", + "@vinejs/vine": "^2.0.0 || ^3.0.0 || ^4.0.0", + "ajv": "^8.12.0", + "ajv-errors": "^3.0.0", + "ajv-formats": "^2.1.1", + "arktype": "^2.0.0", + "ata-validator": "^1.23.0", + "class-transformer": ">=0.4.0", + "class-validator": ">=0.12.0", + "computed-types": "^1.0.0", + "effect": "^3.10.3", + "fluentvalidation-ts": "^3.0.0", + "fp-ts": "^2.7.0", + "io-ts": "^2.0.0", + "joi": "^17.0.0 || ^18.0.0", + "nope-validator": ">=0.12.0", + "react-hook-form": "^7.55.0", + "superstruct": ">=0.12.0", + "typanion": "^3.3.2", + "valibot": ">=0.31.0 || ^1.0.0-beta.4 || ^1.0.0-rc", + "vest": ">=6.0.0", + "yup": "^1.0.0", + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "@sinclair/typebox": { + "optional": true + }, + "@standard-schema/spec": { + "optional": true + }, + "@typeschema/main": { + "optional": true + }, + "@vinejs/vine": { + "optional": true + }, + "ajv": { + "optional": true + }, + "ajv-errors": { + "optional": true + }, + "ajv-formats": { + "optional": true + }, + "arktype": { + "optional": true + }, + "ata-validator": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + }, + "computed-types": { + "optional": true + }, + "effect": { + "optional": true + }, + "fluentvalidation-ts": { + "optional": true + }, + "fp-ts": { + "optional": true + }, + "io-ts": { + "optional": true + }, + "joi": { + "optional": true + }, + "nope-validator": { + "optional": true + }, + "superstruct": { + "optional": true + }, + "typanion": { + "optional": true + }, + "valibot": { + "optional": true + }, + "vest": { + "optional": true + }, + "yup": { + "optional": true + }, + "zod": { + "optional": true + } } }, "node_modules/@humanfs/core": { @@ -2569,15 +2670,15 @@ } }, "node_modules/@next/env": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.8.tgz", - "integrity": "sha512-Al9zqHVV7TJv0eFuOU4U7Lvv74PTih4Ch63sk2xCIpSTkE3udFnaOcnzP2lQVymiL7yS9Cj2iClUXlR3EQ5sEw==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.4.1.tgz", + "integrity": "sha512-5sUUrrSvs/2/2LnLoesybMGx12EtPB46fdZ6RhAw0XDGSPxU2LFyQBB7yuEiOFFJPKmBY6+q2jTr1/AMbnp0/g==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "16.3.4", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.3.4.tgz", - "integrity": "sha512-szW9y2Aumu4z88YXfTzcFsgUAg2k64uzbtcO5L9f1AKS4w/GUKJcbFllRflROVyNPgJtGOnvNxiyp3v6b+prIA==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.4.1.tgz", + "integrity": "sha512-2io6M+wAqe7nT5mt2gEVy6FOzye2DmwhjaYCpSvHfrIKL11SXNTwSARxpPHJacRmfgSBSDnNmnEXSp0DaJ23BQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2618,9 +2719,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.8.tgz", - "integrity": "sha512-2JPRMh2nmQG5CiL7cXGL9AGwnPWJQ//cTtAUCT+w511QHk79SYz3LGv/pc5X643B/WEO0rvu3Yww0hqwt3kgeA==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.4.1.tgz", + "integrity": "sha512-U+hQ5Gj3fpzf4fveTIF3dpUFYhaSW8vHhdAnbiIomzXzg7boreYFgBqprepXFtW4sw+aTttiNmg0gew/iFNhbg==", "cpu": [ "arm64" ], @@ -2634,9 +2735,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.8.tgz", - "integrity": "sha512-GZtCCOBKJ4leVIT/Th0llWKhD1ca92lzbQiS5R5ON9QkoiFnilFsebDae1JU2a3HWoKMEmEZWGs1AGLavVM72Q==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.4.1.tgz", + "integrity": "sha512-/hqC3V1XLUjhMASf/WridKdO9FXoEgN3HBWmtKbj00MPgnltutfraWJ3bYTpCRIgEIpbjJyOVLpYgAhh/BkdcQ==", "cpu": [ "x64" ], @@ -2650,9 +2751,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.8.tgz", - "integrity": "sha512-O659ygeQYqneJ1fBKMpFxIFqYkYswu8IAS1OCKK/4f3ZgJJm1dRz4fVJZRi/kLLWjnBKnebOePA4WNv+sV1pVA==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.4.1.tgz", + "integrity": "sha512-GHzncHbcaS9g95kcvTNtKQW3aCLoR+xc3Jm7qrkpk1R+D2BjMHIPyvQGRPKCdMX95BsH/421jBUK06q9tEwzjw==", "cpu": [ "arm64" ], @@ -2669,9 +2770,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.8.tgz", - "integrity": "sha512-dSjKSyWpzxoO1d3DIZZcP4XJcNaKeLmxQMFOiYl5vuBRMmweIqnAhty8tAmRsvTss779cK1FtYnDMj40e4TQlg==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.4.1.tgz", + "integrity": "sha512-1SuJyDxW/PR9dHJat/ZRgcYLhuSZ+1psP4DlKb2tKIuXbjygqpLrJWRSq+onZQBv8LcmU67EIrmb6c3XTaJLjw==", "cpu": [ "arm64" ], @@ -2688,9 +2789,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.8.tgz", - "integrity": "sha512-lbqOuz3RPRcv+o9msNsJw5x4+Y1ZwPTs6vmL6DCf7i0fZfvng/F59wyeDwqHIvV0mK//RBy/jJkZ+nCKsSMXjQ==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.4.1.tgz", + "integrity": "sha512-Istng1hMGp9TGO4lUqeKLd70MPN/OOkucVTP2Nmj+gLkwBgmPqUw8CJYBCC7nbl/B/23bBCcjCI5Hsh6hazC1A==", "cpu": [ "x64" ], @@ -2707,9 +2808,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.8.tgz", - "integrity": "sha512-+316WswI8ScVgZeUd+1KGaXkHhaYQzCjvH/05TZSpJ8zBizb1a4G7DtO7F12jcBIqMOtsz9ji1t48fmKtzqsGA==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.4.1.tgz", + "integrity": "sha512-aSC9wMNiZRRFVpPkPWBzRwLQxIGm/CiQcXyFF1XNcgodb+uMxdk7aSSGGpDXCbnvZdf4itjHxpOd5h7i7zaiYw==", "cpu": [ "x64" ], @@ -2726,9 +2827,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.8.tgz", - "integrity": "sha512-ji0gd4kMYUxO+1fJBIbiBVRCjzG/lloiyCccnlebvb1ZJ5qXCPZqYg4Jl1DrrixnWNMKylzgpmMWx0yNDYXlzw==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.4.1.tgz", + "integrity": "sha512-t/myvwFDlypMUjRvbBf8qLPyuaB0iXYYdBtwMt6DM6f+60wtGr4bSYholdPqNeV5VUXZhrpMwfza829kmhS3iA==", "cpu": [ "arm64" ], @@ -2742,9 +2843,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.8.tgz", - "integrity": "sha512-WcTlaKt/TWkh5kUjdJcUmB1XgZ+1c6fz4Y9fDHL73YNSdGaUWjceeWrrlwF0nv19iABYWC4iAq1oX1w4Bn0vfg==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.4.1.tgz", + "integrity": "sha512-6ICqPo9awCkrtYNPhwkx1uU7rlFWrZRrIboDHS2LU+jv088UBYQtmJ25h6pCp27/+FZjF6BQ4Te4ErugyMeuBg==", "cpu": [ "x64" ], @@ -3522,30 +3623,54 @@ } }, "node_modules/@sentry/browser": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.73.0.tgz", - "integrity": "sha512-HqTe1S5RrWLufhX2LaFP3yNoMxfNDroh120bq1zdGHZfFDBMJQ0CDXxHO+L4UJfQ5dWdCCzWbXIAiZuWGa/DFQ==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.75.2.tgz", + "integrity": "sha512-2Q8Bd6aTIHmqWL/rGDZdr1JTGW2fYPXf+lMyhHp4CX6OE7gMaaI5ZUwQWgVelqUOvKkOZHHk0wo6K8+ExdwawQ==", "license": "MIT", "dependencies": { - "@sentry/browser-utils": "10.73.0", + "@sentry/browser-utils": "10.75.2", "@sentry/conventions": "^0.16.0", - "@sentry/core": "10.73.0", - "@sentry/feedback": "10.73.0", - "@sentry/replay": "10.73.0", - "@sentry/replay-canvas": "10.73.0" + "@sentry/core": "10.75.2", + "@sentry/feedback": "10.75.2", + "@sentry/replay": "10.75.2", + "@sentry/replay-canvas": "10.75.2" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/browser-utils": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/browser-utils/-/browser-utils-10.73.0.tgz", - "integrity": "sha512-qQygxJZ+RV779+iL1+lrJ4f4sZLgbgW0/JWPNp0YlcEAE62yCsdKbqoTEjB/EugdS4mSjBMX0chZC6rblu2Ycw==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/browser-utils/-/browser-utils-10.75.2.tgz", + "integrity": "sha512-U9RIJE0vZHWEnfEpJAa/SQ60MsNSUaxww4MVymNLwJ26BrLFz9jLhVIW9bXcx0i1iwK+KQbIv6ebPDOnCfYUPQ==", "license": "MIT", "dependencies": { "@sentry/conventions": "^0.16.0", - "@sentry/core": "10.73.0" + "@sentry/core": "10.75.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/browser-utils/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/browser/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" }, "engines": { "node": ">=18" @@ -3798,34 +3923,46 @@ } }, "node_modules/@sentry/feedback": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/feedback/-/feedback-10.73.0.tgz", - "integrity": "sha512-D6nSngX+e46Mae2/oh2bxBvxNK1z2NERbuMAhB5sx9x4xMBWIyGnYYTECehvEqV9+AqGAgxxhOZoYIG3AmRwww==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/feedback/-/feedback-10.75.2.tgz", + "integrity": "sha512-/nrtMVSxOqBAigMWxIQS+Y8OqQ27ty+isMh6+X96kfAp/SaGrNZ425SZxKwq0mwHS0WnVkF+rE5dJnbbi56XSA==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.75.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/feedback/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", "license": "MIT", "dependencies": { - "@sentry/core": "10.73.0" + "@sentry/conventions": "^0.16.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/nextjs": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/nextjs/-/nextjs-10.73.0.tgz", - "integrity": "sha512-lZFlQkafIHnYKTo0QCY+VqFC7rEt/SRAVrTCKyM+r1yIAw+iIfU1qM2QT7xn71+t0U520I0xBJ2O+YzqLYXJIQ==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/nextjs/-/nextjs-10.75.2.tgz", + "integrity": "sha512-ilzb3E7Kaskx/RQ355kCkxLxrHBtYS67pe6KO+F/O6s53f5t4sVwz4gE2Mz4ScghDXeKM+ccyB5GMq9dlkQ35A==", "license": "MIT", "dependencies": { "@opentelemetry/api": "^1.9.1", "@rollup/plugin-commonjs": "28.0.1", - "@sentry/browser-utils": "10.73.0", + "@sentry/browser-utils": "10.75.2", "@sentry/bundler-plugin-core": "^5.3.0", "@sentry/conventions": "^0.16.0", - "@sentry/core": "10.73.0", - "@sentry/node": "10.73.0", - "@sentry/opentelemetry": "10.73.0", - "@sentry/react": "10.73.0", - "@sentry/server-utils": "10.73.0", - "@sentry/vercel-edge": "10.73.0", + "@sentry/core": "10.75.2", + "@sentry/node": "10.75.2", + "@sentry/opentelemetry": "10.75.2", + "@sentry/react": "10.75.2", + "@sentry/server-utils": "10.75.2", + "@sentry/vercel-edge": "10.75.2", "@sentry/webpack-plugin": "^5.3.0", "rollup": "^4.60.3", "stacktrace-parser": "^0.1.11" @@ -3837,20 +3974,32 @@ "next": "^13.2.0 || ^14.0 || ^15.0.0-rc.0 || ^16.0.0-0" } }, + "node_modules/@sentry/nextjs/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@sentry/node": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.73.0.tgz", - "integrity": "sha512-jiMJ6GgXDw6UMGzJY+o0c8OoeA9OfHqZ/xEpHfDqy75hn+9CEkRkbNGCIdMvsc7wW/Se1Os394hHfTpU+YEskg==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.75.2.tgz", + "integrity": "sha512-ffdx1i3Fx9Q3Ofdaone2I+HWOj9+Wcu268xgV+Bn8WJYABm8BZIBNvS+PORKBPesWILhQCThWOs+E/8vcV1HuQ==", "license": "MIT", "dependencies": { "@opentelemetry/api": "^1.9.1", "@opentelemetry/instrumentation": "^0.220.0", "@opentelemetry/sdk-trace-base": "^2.9.0", "@sentry/conventions": "^0.16.0", - "@sentry/core": "10.73.0", - "@sentry/node-core": "10.73.0", - "@sentry/opentelemetry": "10.73.0", - "@sentry/server-utils": "10.73.0", + "@sentry/core": "10.75.2", + "@sentry/node-core": "10.75.2", + "@sentry/opentelemetry": "10.75.2", + "@sentry/server-utils": "10.75.2", "import-in-the-middle": "^3.0.0" }, "engines": { @@ -3858,14 +4007,14 @@ } }, "node_modules/@sentry/node-core": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.73.0.tgz", - "integrity": "sha512-GHAGUmZPmm6FKfxfv2maVVJ/A99YAmd7oFOuKMDmITI6O/Msl6JB3vPTEpopVAHLW0LYJQBOjddL9C7o+Jt44g==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.75.2.tgz", + "integrity": "sha512-6sFhrvWVLAPRTOYkwrOOLwgsWINe6Y75oX9xKj11zZcKd2e1K2Y3bcx3uzDU06+cxfVbUQUBulsCr/TD7yx/vw==", "license": "MIT", "dependencies": { "@sentry/conventions": "^0.16.0", - "@sentry/core": "10.73.0", - "@sentry/opentelemetry": "10.73.0", + "@sentry/core": "10.75.2", + "@sentry/opentelemetry": "10.75.2", "import-in-the-middle": "^3.0.0" }, "engines": { @@ -3896,14 +4045,38 @@ } } }, + "node_modules/@sentry/node-core/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/node/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@sentry/opentelemetry": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.73.0.tgz", - "integrity": "sha512-fQouPQKsH0CQrw6oAn1k0Z2I+tgyochCovifr5qNS69i0OzjknLa03WJyiZ/IuzXc4AVa5jAKfOeE9slABz8Qw==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.75.2.tgz", + "integrity": "sha512-qoJIdrXiFPPYs7AmdkktB5O4vhHYKzk6EulpQlvROe+ZZeG4/S0yeJApAbg3ThDob/2zEAxYEPEvaHv2epipgA==", "license": "MIT", "dependencies": { "@sentry/conventions": "^0.16.0", - "@sentry/core": "10.73.0" + "@sentry/core": "10.75.2" }, "engines": { "node": ">=18" @@ -3914,15 +4087,27 @@ "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0" } }, + "node_modules/@sentry/opentelemetry/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@sentry/react": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.73.0.tgz", - "integrity": "sha512-wJrzS98ddPvhGS/MKNHZyE8X7ecd4KwKdz7fHino2qkqBBrF4cxWr+q/uLTIk5PYWMkeJ4oKMjHAjOqmzGR4tg==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.75.2.tgz", + "integrity": "sha512-4MtB1tSmMHzwTwY7m30UzRbbUx9cP84UK7WIDL9g7RvoGd/aZwxbp6IkUJ46VBNItVoSF+1GM9wtqzkLma252g==", "license": "MIT", "dependencies": { - "@sentry/browser": "10.73.0", + "@sentry/browser": "10.75.2", "@sentry/conventions": "^0.16.0", - "@sentry/core": "10.73.0" + "@sentry/core": "10.75.2" }, "engines": { "node": ">=18" @@ -3931,53 +4116,113 @@ "react": "^16.14.0 || 17.x || 18.x || 19.x" } }, + "node_modules/@sentry/react/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@sentry/replay": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-10.73.0.tgz", - "integrity": "sha512-nN2wjN/Y0J5BOJV5hqRHUEBfxwUsipp1PKjcDHh6Fpxnrtfldu3Y99E8cQInseo5heFdzEvrOHBBrqWZXOHVKQ==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-10.75.2.tgz", + "integrity": "sha512-cCfdPt892S+rrAFOuUvbwR318/ZPFfBFvVkMlL3goktAnbECAGy6comAxLQEalyp22Ee67bEqYQN7RdNuRHIJw==", "license": "MIT", "dependencies": { - "@sentry/browser-utils": "10.73.0", - "@sentry/core": "10.73.0" + "@sentry/browser-utils": "10.75.2", + "@sentry/core": "10.75.2" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/replay-canvas": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/replay-canvas/-/replay-canvas-10.73.0.tgz", - "integrity": "sha512-sxa2lKkHPfF/j5xFpW7gocthWXRqyoHz8KCPy6yGc8plT477nl57iGSKhQDYsx1Ny10TLjs7YkIuPP1GY/Ax2Q==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/replay-canvas/-/replay-canvas-10.75.2.tgz", + "integrity": "sha512-4GVhCkn+/0QEpXdY8UfXahg8qjF2QTH1+qej/CLketHGfRqxLhdanzHU9ILesplWX5GeuTkPn5ZTmd5CJf+KXg==", "license": "MIT", "dependencies": { - "@sentry/core": "10.73.0", - "@sentry/replay": "10.73.0" + "@sentry/core": "10.75.2", + "@sentry/replay": "10.75.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/replay-canvas/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/replay/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/server-utils": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/server-utils/-/server-utils-10.73.0.tgz", - "integrity": "sha512-QskripdKFbM/+gipC6mpa2crLwL7+VbkX84IpHg2z9UlYQ1kNKd3aMT+Qk9NLRSw/zu1rSIAvlbWfx4D3rgNAA==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/server-utils/-/server-utils-10.75.2.tgz", + "integrity": "sha512-ep8Ntj/vsLHbql1jUMFiRYrleuQ3dENb8oD4Nkjv7hou2j0UKLct1eLbx+TckeVOhYdWmFeO7WJWjRio/a4TOg==", "license": "MIT", "dependencies": { "@sentry/conventions": "^0.16.0", - "@sentry/core": "10.73.0" + "@sentry/core": "10.75.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/server-utils/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/vercel-edge": { - "version": "10.73.0", - "resolved": "https://registry.npmjs.org/@sentry/vercel-edge/-/vercel-edge-10.73.0.tgz", - "integrity": "sha512-DJLqVzd3ng4IwR+ux/vK1Wth/CSwUrsiwIbNsyneHw79cyhfjYuovFTw1xrjn9zTJoVSE8KkdajLSLwmLbnoTw==", + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/vercel-edge/-/vercel-edge-10.75.2.tgz", + "integrity": "sha512-Ol2kQfob60s4qAeitUt2XXG9of/jUCqhQ3loMx5nASJn9Y1C86XZOqzbVuzBDIoMQVBPV2JGCD8HgWHiN5HPbw==", "license": "MIT", "dependencies": { "@opentelemetry/api": "^1.9.1", - "@sentry/core": "10.73.0" + "@sentry/core": "10.75.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/vercel-edge/node_modules/@sentry/core": { + "version": "10.75.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.75.2.tgz", + "integrity": "sha512-KXzNf2c430cJIOMv84+MKpkXgave1DBNMNNwn073olVD773NME5IhDv/9VQyiFM2wIU+6bm4FEBVEVSuzqgjJw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" }, "engines": { "node": ">=18" @@ -4004,6 +4249,12 @@ "integrity": "sha512-BE/UWv6FOToAdVk0EokzkqQQDOWtNydYlY6+OrmiZ5SCNmb41VehttboTetUM3T/fr6EAFYVXjz4My2wg230rQ==", "license": "MIT" }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, "node_modules/@swagger-api/apidom-ast": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-1.11.6.tgz", @@ -7147,9 +7398,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.1.tgz", - "integrity": "sha512-Ca8swihM+/4yKecYHY52kgJd300hi2lADU/a1RxNTRe+RJ9jvqQlESpbz9DnG9mowez8qwXHB8qYdIUw9e+F5Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.3.0.tgz", + "integrity": "sha512-lmNyBzi6iYiqyrExTctfmjd8tInx+dHu9PBomTfH5RXS53c27JMFJgzNv5TyAnm3PgGf+MLy0+Ws41/HlVxdKQ==", "license": "MIT" }, "node_modules/class-variance-authority": { @@ -7620,9 +7871,9 @@ "peer": true }, "node_modules/dompurify": { - "version": "3.4.16", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.16.tgz", - "integrity": "sha512-sqo+pNp3qRhCIpbgRi1y8Tgk27Bo2Ry7w0dC1NBeNTdZChWjz9Xb/KOoZbRP/R6pQZ80Qw8YhXw13hWWBbMRnQ==", + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.17.tgz", + "integrity": "sha512-B/pSlYVHQ58kqISD/yDjuJ1yfzI34m1gF4lAod2bwSRhiN4K5Cl3H8Af7hqB2PmTL911tdEudnnXn5FnhRoz0w==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -7840,7 +8091,8 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/es-object-atoms": { "version": "1.1.2", @@ -8029,21 +8281,21 @@ } }, "node_modules/eslint-config-next": { - "version": "16.3.4", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.3.4.tgz", - "integrity": "sha512-35/8RM10huEL9vlr8hUZMERMENHBrnyHN3ZZkF9efSgzGaqK34jIqry44A956//zriUhUAUW0XSkcolhrryqAA==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.4.1.tgz", + "integrity": "sha512-6AsojbCfRdpWkP6BIUnMBv3MH4OvtfmH9p4hSfLh8ZgsW7nfhu7DpUMNBB7leisDyyMz+YYxTc+NAdBOQfovlA==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "16.3.4", + "@next/eslint-plugin-next": "16.4.1", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", - "eslint-plugin-react-hooks": "^7.0.0", + "eslint-plugin-react-hooks": "^7.1.0", "globals": "16.4.0", - "typescript-eslint": "^8.46.0" + "typescript-eslint": "^8.56.0" }, "peerDependencies": { "eslint": ">=9.0.0", @@ -9300,19 +9552,25 @@ } }, "node_modules/import-in-the-middle": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-3.4.0.tgz", - "integrity": "sha512-Xfjwfarhe+LGmoaof+sexeNo3sGRysb5x56WrZLwHtmqT0OilSKtVWkv0lrCcMgSKyKP9oBogBAisHZvtJH0aw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-3.5.2.tgz", + "integrity": "sha512-WseIA/4o56+GYO3RmlOPvejYi771OFeJEeK/ejROsr9bdjW+E5NXTOD1Di8TL40Qgg3JJX9aa97Hf8iiSVIKZw==", "license": "Apache-2.0", "dependencies": { "cjs-module-lexer": "^2.2.0", - "es-module-lexer": "^2.2.0", + "es-module-lexer": "^3.0.2", "module-details-from-path": "^1.0.4" }, "engines": { "node": ">=18" } }, + "node_modules/import-in-the-middle/node_modules/es-module-lexer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-3.0.4.tgz", + "integrity": "sha512-BldNY5mwkVu+cQ5Ymn3e6hB9Sx8XHx4ZevWbiUyZbfKxJxYO27Hf0wfzkxIaD5CAJMaGl3YspKELj0ff/7nCMA==", + "license": "MIT" + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -11742,12 +12000,12 @@ } }, "node_modules/next": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/next/-/next-16.3.8.tgz", - "integrity": "sha512-U7QEZaTini6wKrb8A8hqLLqYQyCetegKjCpJOyxk642vWoMoU1x5PyZCJFvgYgiptA8xc5j/9xYlZFO7w9Sjmw==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/next/-/next-16.4.1.tgz", + "integrity": "sha512-uc657V62E34fOI6W5NtG9IzwsPcms0Z60grz2MJGtglgD+pTFnNt4Yw2PzaU622tfX4vhrDgLZzicE2YlhI20Q==", "license": "MIT", "dependencies": { - "@next/env": "16.3.8", + "@next/env": "16.4.1", "@swc/helpers": "0.5.23", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", @@ -11761,15 +12019,15 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "16.3.8", - "@next/swc-darwin-x64": "16.3.8", - "@next/swc-linux-arm64-gnu": "16.3.8", - "@next/swc-linux-arm64-musl": "16.3.8", - "@next/swc-linux-x64-gnu": "16.3.8", - "@next/swc-linux-x64-musl": "16.3.8", - "@next/swc-win32-arm64-msvc": "16.3.8", - "@next/swc-win32-x64-msvc": "16.3.8", - "sharp": "^0.35.4" + "@next/swc-darwin-arm64": "16.4.1", + "@next/swc-darwin-x64": "16.4.1", + "@next/swc-linux-arm64-gnu": "16.4.1", + "@next/swc-linux-arm64-musl": "16.4.1", + "@next/swc-linux-x64-gnu": "16.4.1", + "@next/swc-linux-x64-musl": "16.4.1", + "@next/swc-win32-arm64-msvc": "16.4.1", + "@next/swc-win32-x64-msvc": "16.4.1", + "sharp": "^0.35.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -15336,9 +15594,9 @@ "license": "Unlicense" }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", + "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -15369,7 +15627,7 @@ }, "packages/codefly-ui": { "name": "@codefly-dev/ui", - "version": "0.12.15", + "version": "0.13.0", "license": "Apache-2.0", "dependencies": { "@base-ui/react": "^1.3.0", @@ -15518,7 +15776,7 @@ }, "packages/saas-ui": { "name": "@codefly-dev/saas-ui", - "version": "0.12.15", + "version": "0.13.0", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "1.9.1", @@ -15530,31 +15788,31 @@ "devDependencies": { "@bufbuild/protobuf": "^2.11.0", "@codefly-dev/saas-sdk": "^0.3.35", - "@codefly-dev/ui": "^0.12.0", + "@codefly-dev/ui": "^0.13.0", "@connectrpc/connect": "^2.1.1", "@connectrpc/connect-web": "^2.1.1", - "@hookform/resolvers": "^3.9.0", + "@hookform/resolvers": "^5.9.2", "@tanstack/react-query": "^5.60.0", "@testing-library/react": "^16.1.0", "@types/react": "19.2.17", "happy-dom": "^20.8.9", "react": "^19.2.8", - "react-hook-form": "^7.54.0", + "react-hook-form": "^7.55.0", "typescript": "5.9.3", "vitest": "^3.0.0", - "zod": "^3.24.0" + "zod": "^4.6.6" }, "peerDependencies": { "@bufbuild/protobuf": ">=2", "@codefly-dev/saas-sdk": "^0.3.35", - "@codefly-dev/ui": "^0.12.0", + "@codefly-dev/ui": "^0.13.0", "@connectrpc/connect": ">=2", "@connectrpc/connect-web": ">=2", - "@hookform/resolvers": ">=3", + "@hookform/resolvers": ">=5.1.0", "@tanstack/react-query": ">=5", "react": ">=19.2 <20", - "react-hook-form": ">=7", - "zod": ">=3" + "react-hook-form": ">=7.55.0", + "zod": "^4.6.6" } } } diff --git a/module/services/frontend/code/package.json b/module/services/frontend/code/package.json index f3277d9e8..719e620b9 100644 --- a/module/services/frontend/code/package.json +++ b/module/services/frontend/code/package.json @@ -40,8 +40,8 @@ "@codefly-dev/saas-plugin-contract": "2.4.4", "@codefly-dev/saas-plugin-react": "0.4.5", "@codefly-dev/saas-sdk": "0.3.35", - "@codefly-dev/saas-ui": "0.12.8", - "@codefly-dev/ui": "0.12.8", + "@codefly-dev/saas-ui": "0.13.0", + "@codefly-dev/ui": "0.13.0", "@codefly/saas-plugin-manifest": "0.1.2", "@codefly/saas-settings": "0.1.0", "@connectrpc/connect": "^2.1.1", @@ -52,9 +52,9 @@ "@fontsource/newsreader": "^5.3.0", "@fontsource/roboto": "^5.3.0", "@fontsource/source-serif-4": "^5.3.0", - "@hookform/resolvers": "^3.9.0", + "@hookform/resolvers": "^5.9.2", "@module-federation/runtime": "^2.8.2", - "@sentry/nextjs": "^10.50.0", + "@sentry/nextjs": "10.75.2", "@simplewebauthn/browser": "^13.3.0", "@tanstack/react-query": "^5.60.0", "@tanstack/react-table": "^8.21.3", @@ -62,16 +62,16 @@ "codefly": "https://github.com/codefly-dev/sdk-js/archive/9f3bb78682a0c2b9a70631d35c2ae0094c281ac5.tar.gz", "js-yaml": "^4.3.2", "lucide-react": "^1.8.0", - "next": "^16.2.12", + "next": "16.4.1", "react": "^19.2.8", "react-dom": "^19.2.8", - "react-hook-form": "^7.54.0", + "react-hook-form": "^7.55.0", "server-only": "^0.0.1", "sonner": "^2.0.7", "swagger-ui-react": "^5.32.14", "tailwind-merge": "^3.5.0", "tw-animate-css": "^1.4.0", - "zod": "^3.24.0" + "zod": "^4.6.6" }, "devDependencies": { "@biomejs/biome": "^2.5.4", @@ -88,7 +88,7 @@ "ajv": "^8.17.1", "babel-plugin-react-compiler": "1.0.0", "eslint": "^9.39.5", - "eslint-config-next": "^16.2.12", + "eslint-config-next": "16.4.1", "happy-dom": "^20.8.9", "jsdom": "^29.0.2", "msw": "^2.7.0", diff --git a/module/services/frontend/code/packages/codefly-ui/package.json b/module/services/frontend/code/packages/codefly-ui/package.json index af8fac509..16c35d906 100644 --- a/module/services/frontend/code/packages/codefly-ui/package.json +++ b/module/services/frontend/code/packages/codefly-ui/package.json @@ -1,6 +1,6 @@ { "name": "@codefly-dev/ui", - "version": "0.12.15", + "version": "0.13.0", "description": "The shared, versioned Codefly SaaS frontend kit: the plugin host and the tokens-as-data skin mechanism, standalone so the host and Module-Federation remotes import and dedupe one copy.", "repository": { "type": "git", diff --git a/module/services/frontend/code/packages/saas-ui/README.md b/module/services/frontend/code/packages/saas-ui/README.md index 428c2bcca..529c15a23 100644 --- a/module/services/frontend/code/packages/saas-ui/README.md +++ b/module/services/frontend/code/packages/saas-ui/README.md @@ -583,6 +583,19 @@ elapsed through `Intl.RelativeTimeFormat`, for a consumer's own shell. ## Installing from a solution +Version 0.13 requires Zod `^4.6.6`, `@hookform/resolvers >=5.1.0` and +React Hook Form `>=7.55.0`. The exported source schemas use Zod 4 declarations +and its `check` refinement hook; Zod 3 cannot consume them. Zod 4.6.6 is the +minimum patched release for GHSA-mrhx-c7xc-m3w5. The resolver must understand +Zod 4 errors so invalid form input becomes a field error instead of a thrown +exception. The co-versioned `@codefly-dev/ui` peer is `^0.13.0`. + +The `example-registry-ui` consumer in `scripts/test-registry-ui.mjs` installs +packed packages through a registry fixture, compiles imports of both source +schemas and their inferred value types, and exercises valid, missing-token and +oversized-scope input through the form resolver. Run it from the frontend with +`npm run test:published-ui` after building the workspace packages. + This package is published to GitHub Packages under the org's `@codefly-dev` scope, so a consumer needs that scope routed to the GitHub registry with a read token: diff --git a/module/services/frontend/code/packages/saas-ui/package.json b/module/services/frontend/code/packages/saas-ui/package.json index 89b66f66f..042a71cf1 100644 --- a/module/services/frontend/code/packages/saas-ui/package.json +++ b/module/services/frontend/code/packages/saas-ui/package.json @@ -1,6 +1,6 @@ { "name": "@codefly-dev/saas-ui", - "version": "0.12.15", + "version": "0.13.0", "description": "Reusable SaaS-domain frontend components (datasources, …) the portal and solutions both import, built on @codefly-dev/ui primitives and driven by an injected typed client.", "repository": { "type": "git", @@ -44,29 +44,29 @@ "@codefly-dev/saas-sdk": "^0.3.35", "@connectrpc/connect": ">=2", "@connectrpc/connect-web": ">=2", - "@hookform/resolvers": ">=3", + "@hookform/resolvers": ">=5.1.0", "@tanstack/react-query": ">=5", "react": ">=19.2 <20", - "react-hook-form": ">=7", - "zod": ">=3", - "@codefly-dev/ui": "^0.12.0" + "react-hook-form": ">=7.55.0", + "zod": "^4.6.6", + "@codefly-dev/ui": "^0.13.0" }, "devDependencies": { "@bufbuild/protobuf": "^2.11.0", "@codefly-dev/saas-sdk": "^0.3.35", "@connectrpc/connect": "^2.1.1", "@connectrpc/connect-web": "^2.1.1", - "@hookform/resolvers": "^3.9.0", + "@hookform/resolvers": "^5.9.2", "@tanstack/react-query": "^5.60.0", "@testing-library/react": "^16.1.0", "@types/react": "19.2.17", "happy-dom": "^20.8.9", "react": "^19.2.8", - "react-hook-form": "^7.54.0", + "react-hook-form": "^7.55.0", "typescript": "5.9.3", "vitest": "^3.0.0", - "zod": "^3.24.0", - "@codefly-dev/ui": "^0.12.0" + "zod": "^4.6.6", + "@codefly-dev/ui": "^0.13.0" }, "publishConfig": { "access": "public" diff --git a/module/services/frontend/code/packages/saas-ui/src/datasources/schema.ts b/module/services/frontend/code/packages/saas-ui/src/datasources/schema.ts index ef685af9a..08aaa8c2a 100644 --- a/module/services/frontend/code/packages/saas-ui/src/datasources/schema.ts +++ b/module/services/frontend/code/packages/saas-ui/src/datasources/schema.ts @@ -77,14 +77,16 @@ export const connectGitHubSchema = z accessToken: z.string().max(1024, "Access token too long").optional(), webhookSecret: z.string().max(1024, "Webhook secret too long").optional(), }) - .superRefine((values, ctx) => { + .check((ctx) => { + const values = ctx.value; if ( values.method !== "app" && values.method !== "public" && !values.accessToken ) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, + ctx.issues.push({ + input: values, + code: "custom", path: ["accessToken"], message: "Access token is required", }); diff --git a/module/services/frontend/code/scripts/test-registry-ui.mjs b/module/services/frontend/code/scripts/test-registry-ui.mjs index da913ac49..55d2c4c9e 100644 --- a/module/services/frontend/code/scripts/test-registry-ui.mjs +++ b/module/services/frontend/code/scripts/test-registry-ui.mjs @@ -169,8 +169,28 @@ import { createTaskTracker, mountIsolated } from "@codefly-dev/ui/lifecycle"; import { resolveSkin } from "@codefly-dev/ui/skin"; import { PluginRuntimeProvider, usePluginRuntime } from "@codefly-dev/ui/plugin-host/runtime"; import { PluginRuntimeProvider as DirectProvider, usePluginRuntime as directHook } from "@codefly-dev/saas-plugin-react/runtime"; -import { ConnectGitHubForm } from "@codefly-dev/saas-ui"; +import { ConnectGitHubForm, connectGitHubSchema, editSourceSchema, type ConnectGitHubValues, type EditSourceValues } from "@codefly-dev/saas-ui"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import type { Resolver } from "react-hook-form"; import { DirectoryService } from "@codefly-dev/saas-sdk"; +const schema: z.ZodType = connectGitHubSchema; +const connection: ConnectGitHubValues = schema.parse({ method: "public", repo: "Acme/example", targetCollection: "example" }); +const scope: EditSourceValues = editSourceSchema.parse({ paths: "docs/", fileExtensions: ".md" }); +if (connection.accessToken !== undefined || scope.paths !== "docs/") throw new Error("Schema output changed"); +const resolveConnection: Resolver = zodResolver(connectGitHubSchema); +const resolveScope: Resolver = zodResolver(editSourceSchema); +async function proveSchemaValidation() { + const options = { fields: {}, shouldUseNativeValidation: false }; + const accepted = await resolveConnection(connection, undefined, options); + if (Object.keys(accepted.errors).length) throw new Error("Public connection rejected"); + const refused = await resolveConnection({ ...connection, method: "pat" }, undefined, options); + if (refused.errors.accessToken?.message !== "Access token is required") throw new Error("Missing token field error"); + const bounded = await resolveScope({ paths: Array.from({ length: 65 }, (_, i) => "path" + i).join(",") }, undefined, options); + if (!bounded.errors.paths) throw new Error("Oversized scope accepted"); + console.log("Registry consumer schema types and form validation passed"); +} +void proveSchemaValidation(); for (const value of [Disclosure, Accordion, Breadcrumb, Tree, RadioGroup, Surface, Timeline, ViewportOverlay, createTaskTracker, mountIsolated, resolveSkin, ConnectGitHubForm, DirectoryService]) { if (!value) throw new Error("Missing public export"); } diff --git a/module/services/frontend/code/src/features/teams/ui/team-form.tsx b/module/services/frontend/code/src/features/teams/ui/team-form.tsx index 5c0ecd08f..0807b5fb5 100644 --- a/module/services/frontend/code/src/features/teams/ui/team-form.tsx +++ b/module/services/frontend/code/src/features/teams/ui/team-form.tsx @@ -37,7 +37,7 @@ export function TeamForm({ error, }: TeamFormProps) { const editing = mode === "edit"; - const form = useForm({ + const form = useForm({ resolver: zodResolver(createTeamSchema), defaultValues: { name: initial?.name ?? "", diff --git a/module/services/frontend/service.codefly.yaml b/module/services/frontend/service.codefly.yaml index 3d86ff03c..57d6635bb 100644 --- a/module/services/frontend/service.codefly.yaml +++ b/module/services/frontend/service.codefly.yaml @@ -7,7 +7,18 @@ agent: # the release that ships the builder fix the content kit needs. 0.0.163 also # carries core v0.15.1's NewAPI fix (an endpoint keeps its exposure and # location) and the ConfigMap quoting fix. - version: 0.0.163 + # + # 0.0.167 is the security floor. The agent pins the framework EXACTLY in + # `base/code` and `templates/factory/code`, and its framework gate holds the + # lockfile's resolved version equal to the declared one, so no service built + # by it can resolve past the agent's pin. Through 0.0.166 that pin was + # next 16.3.6, which carries three criticals: unauthenticated RCE in the + # Image Optimization API via SVG (GHSA-2464-fhr4-w9xw), DoS in App Router + # Server Actions (GHSA-p3m5-59mp-jv5r), and RCE in `use cache` functions + # returning typed arrays (GHSA-673q-mjm6-r5xr). 0.0.167 ships next 16.4.1 + # (service-nextjs#177), and with it Go 1.27.3 for GO-2026-6809 (#178) and + # typescript back to ^5, the only major typescript-eslint@8 admits (#179). + version: 0.0.167 publisher: codefly.dev service-dependencies: - name: auth-gateway diff --git a/module/services/marketing/code/package-lock.json b/module/services/marketing/code/package-lock.json index 2bc7701a4..3a7a728b0 100644 --- a/module/services/marketing/code/package-lock.json +++ b/module/services/marketing/code/package-lock.json @@ -8,11 +8,11 @@ "name": "@codefly/marketing", "version": "0.0.1", "dependencies": { - "next": "^16.2.12", + "next": "16.4.1", "react": "^19.2.8", "react-dom": "^19.2.8", "yaml": "^2.8.1", - "zod": "^3.24.0" + "zod": "^4.6.6" }, "devDependencies": { "@types/node": "20.19.39", @@ -1024,15 +1024,15 @@ } }, "node_modules/@next/env": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.8.tgz", - "integrity": "sha512-Al9zqHVV7TJv0eFuOU4U7Lvv74PTih4Ch63sk2xCIpSTkE3udFnaOcnzP2lQVymiL7yS9Cj2iClUXlR3EQ5sEw==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.4.1.tgz", + "integrity": "sha512-5sUUrrSvs/2/2LnLoesybMGx12EtPB46fdZ6RhAw0XDGSPxU2LFyQBB7yuEiOFFJPKmBY6+q2jTr1/AMbnp0/g==", "license": "MIT" }, "node_modules/@next/swc-darwin-arm64": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.8.tgz", - "integrity": "sha512-2JPRMh2nmQG5CiL7cXGL9AGwnPWJQ//cTtAUCT+w511QHk79SYz3LGv/pc5X643B/WEO0rvu3Yww0hqwt3kgeA==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.4.1.tgz", + "integrity": "sha512-U+hQ5Gj3fpzf4fveTIF3dpUFYhaSW8vHhdAnbiIomzXzg7boreYFgBqprepXFtW4sw+aTttiNmg0gew/iFNhbg==", "cpu": [ "arm64" ], @@ -1046,9 +1046,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.8.tgz", - "integrity": "sha512-GZtCCOBKJ4leVIT/Th0llWKhD1ca92lzbQiS5R5ON9QkoiFnilFsebDae1JU2a3HWoKMEmEZWGs1AGLavVM72Q==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.4.1.tgz", + "integrity": "sha512-/hqC3V1XLUjhMASf/WridKdO9FXoEgN3HBWmtKbj00MPgnltutfraWJ3bYTpCRIgEIpbjJyOVLpYgAhh/BkdcQ==", "cpu": [ "x64" ], @@ -1062,9 +1062,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.8.tgz", - "integrity": "sha512-O659ygeQYqneJ1fBKMpFxIFqYkYswu8IAS1OCKK/4f3ZgJJm1dRz4fVJZRi/kLLWjnBKnebOePA4WNv+sV1pVA==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.4.1.tgz", + "integrity": "sha512-GHzncHbcaS9g95kcvTNtKQW3aCLoR+xc3Jm7qrkpk1R+D2BjMHIPyvQGRPKCdMX95BsH/421jBUK06q9tEwzjw==", "cpu": [ "arm64" ], @@ -1081,9 +1081,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.8.tgz", - "integrity": "sha512-dSjKSyWpzxoO1d3DIZZcP4XJcNaKeLmxQMFOiYl5vuBRMmweIqnAhty8tAmRsvTss779cK1FtYnDMj40e4TQlg==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.4.1.tgz", + "integrity": "sha512-1SuJyDxW/PR9dHJat/ZRgcYLhuSZ+1psP4DlKb2tKIuXbjygqpLrJWRSq+onZQBv8LcmU67EIrmb6c3XTaJLjw==", "cpu": [ "arm64" ], @@ -1100,9 +1100,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.8.tgz", - "integrity": "sha512-lbqOuz3RPRcv+o9msNsJw5x4+Y1ZwPTs6vmL6DCf7i0fZfvng/F59wyeDwqHIvV0mK//RBy/jJkZ+nCKsSMXjQ==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.4.1.tgz", + "integrity": "sha512-Istng1hMGp9TGO4lUqeKLd70MPN/OOkucVTP2Nmj+gLkwBgmPqUw8CJYBCC7nbl/B/23bBCcjCI5Hsh6hazC1A==", "cpu": [ "x64" ], @@ -1119,9 +1119,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.8.tgz", - "integrity": "sha512-+316WswI8ScVgZeUd+1KGaXkHhaYQzCjvH/05TZSpJ8zBizb1a4G7DtO7F12jcBIqMOtsz9ji1t48fmKtzqsGA==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.4.1.tgz", + "integrity": "sha512-aSC9wMNiZRRFVpPkPWBzRwLQxIGm/CiQcXyFF1XNcgodb+uMxdk7aSSGGpDXCbnvZdf4itjHxpOd5h7i7zaiYw==", "cpu": [ "x64" ], @@ -1138,9 +1138,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.8.tgz", - "integrity": "sha512-ji0gd4kMYUxO+1fJBIbiBVRCjzG/lloiyCccnlebvb1ZJ5qXCPZqYg4Jl1DrrixnWNMKylzgpmMWx0yNDYXlzw==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.4.1.tgz", + "integrity": "sha512-t/myvwFDlypMUjRvbBf8qLPyuaB0iXYYdBtwMt6DM6f+60wtGr4bSYholdPqNeV5VUXZhrpMwfza829kmhS3iA==", "cpu": [ "arm64" ], @@ -1154,9 +1154,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.8.tgz", - "integrity": "sha512-WcTlaKt/TWkh5kUjdJcUmB1XgZ+1c6fz4Y9fDHL73YNSdGaUWjceeWrrlwF0nv19iABYWC4iAq1oX1w4Bn0vfg==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.4.1.tgz", + "integrity": "sha512-6ICqPo9awCkrtYNPhwkx1uU7rlFWrZRrIboDHS2LU+jv088UBYQtmJ25h6pCp27/+FZjF6BQ4Te4ErugyMeuBg==", "cpu": [ "x64" ], @@ -1339,12 +1339,12 @@ } }, "node_modules/next": { - "version": "16.3.8", - "resolved": "https://registry.npmjs.org/next/-/next-16.3.8.tgz", - "integrity": "sha512-U7QEZaTini6wKrb8A8hqLLqYQyCetegKjCpJOyxk642vWoMoU1x5PyZCJFvgYgiptA8xc5j/9xYlZFO7w9Sjmw==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/next/-/next-16.4.1.tgz", + "integrity": "sha512-uc657V62E34fOI6W5NtG9IzwsPcms0Z60grz2MJGtglgD+pTFnNt4Yw2PzaU622tfX4vhrDgLZzicE2YlhI20Q==", "license": "MIT", "dependencies": { - "@next/env": "16.3.8", + "@next/env": "16.4.1", "@swc/helpers": "0.5.23", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", @@ -1358,15 +1358,15 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "16.3.8", - "@next/swc-darwin-x64": "16.3.8", - "@next/swc-linux-arm64-gnu": "16.3.8", - "@next/swc-linux-arm64-musl": "16.3.8", - "@next/swc-linux-x64-gnu": "16.3.8", - "@next/swc-linux-x64-musl": "16.3.8", - "@next/swc-win32-arm64-msvc": "16.3.8", - "@next/swc-win32-x64-msvc": "16.3.8", - "sharp": "^0.35.4" + "@next/swc-darwin-arm64": "16.4.1", + "@next/swc-darwin-x64": "16.4.1", + "@next/swc-linux-arm64-gnu": "16.4.1", + "@next/swc-linux-arm64-musl": "16.4.1", + "@next/swc-linux-x64-gnu": "16.4.1", + "@next/swc-linux-x64-musl": "16.4.1", + "@next/swc-win32-arm64-msvc": "16.4.1", + "@next/swc-win32-x64-msvc": "16.4.1", + "sharp": "^0.35.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -1609,9 +1609,9 @@ } }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", + "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/module/services/marketing/code/package.json b/module/services/marketing/code/package.json index c15dbbc38..a5a0b456e 100644 --- a/module/services/marketing/code/package.json +++ b/module/services/marketing/code/package.json @@ -18,11 +18,11 @@ "test:smoke": "node scripts/smoke.mjs" }, "dependencies": { - "next": "^16.2.12", + "next": "16.4.1", "react": "^19.2.8", "react-dom": "^19.2.8", "yaml": "^2.8.1", - "zod": "^3.24.0" + "zod": "^4.6.6" }, "devDependencies": { "@types/node": "20.19.39", diff --git a/module/services/marketing/code/src/config/environment.ts b/module/services/marketing/code/src/config/environment.ts index dedb59c30..65578b34f 100644 --- a/module/services/marketing/code/src/config/environment.ts +++ b/module/services/marketing/code/src/config/environment.ts @@ -1,6 +1,7 @@ import { z } from "zod"; -const localOrHTTPSURL = z.string().url().superRefine((value, context) => { +const localOrHTTPSURL = z.string().url().check((context) => { + const value = context.value; const url = new URL(value); if ( url.username || @@ -10,8 +11,9 @@ const localOrHTTPSURL = z.string().url().superRefine((value, context) => { !url.hostname.endsWith(".localhost") && !url.hostname.endsWith(".svc.cluster.local")) ) { - context.addIssue({ - code: z.ZodIssueCode.custom, + context.issues.push({ + input: value, + code: "custom", message: "must be HTTPS outside localhost or an in-cluster service", }); } diff --git a/module/services/marketing/code/tests/catalog.test.ts b/module/services/marketing/code/tests/catalog.test.ts index 329cd97e6..885465a56 100644 --- a/module/services/marketing/code/tests/catalog.test.ts +++ b/module/services/marketing/code/tests/catalog.test.ts @@ -80,7 +80,7 @@ test("rejects checkout secrets and unsupported intervals", () => { revision: "catalog-v1", plans: [{ ...plan, interval: "quarter" }], }), - /invalid enum/i, + /invalid option/i, ); }); diff --git a/module/services/marketing/service.codefly.yaml b/module/services/marketing/service.codefly.yaml index f81aa4ff8..bf38982f6 100644 --- a/module/services/marketing/service.codefly.yaml +++ b/module/services/marketing/service.codefly.yaml @@ -7,7 +7,10 @@ description: | agent: kind: codefly:service name: nextjs - version: 0.0.163 + # 0.0.167 is the security floor: the agent pinned next 16.3.6 exactly through + # 0.0.166, and no service it builds can resolve past its pin. See frontend's + # manifest for the three advisories that pin cleared (service-nextjs#177). + version: 0.0.167 publisher: codefly.dev endpoints: - name: http