diff --git a/.agents/skills/elsa-release/SKILL.md b/.agents/skills/elsa-release/SKILL.md index 5acd1f5020..80c9037b5c 100644 --- a/.agents/skills/elsa-release/SKILL.md +++ b/.agents/skills/elsa-release/SKILL.md @@ -15,7 +15,7 @@ description: Release Elsa from elsa-core as one tag, one GitHub release and one - `.github/workflows/packages.yml` runs on `release: published`, pushes to `main` and `release/*`, and `workflow_dispatch`. A release or push only tests, builds and uploads the `elsa-nuget-packages` artifact. It never publishes. Publication needs an approved `workflow_dispatch` with `publish_preview_feedz` (Feedz: a branch, or a `3.10.x` prerelease tag) or `publish_nuget` (nuget.org: a release-version tag, including stable `3.10.x`). Stable 3.10.x Feedz is owned only by `publish-consolidated-original-candidate.yml`. - Stable `3.10.x` nuget.org publishing is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)). Both the `packages.yml` promote path and `publish-consolidated-original-candidate.yml` run `scripts/validate_packages_id_set.py` on the current pin (run/artifact `11412848210`, 225 packages) before any push, so that set cannot be published as 3.10.0. After #9016 re-pins a fresh candidate from the `release/3.10.0` tip, nuget.org promotion and the candidate Feedz publish can proceed. Neither workflow is part of the ordinary release-train helper. -- `studio-npm-pair.yml` only proves that the two Studio npm archives can be built and consumed locally. Nothing in core publishes them to npm or Feedz yet. Stable 3.10.x nuget.org publication is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)) (part of [#8725](https://github.com/elsa-workflows/elsa-core/issues/8725)); npm publication remains pending. +- `studio-npm-pair.yml` only proves that the two Studio npm archives can be built and consumed locally. `packages.yml` `publish_npm` publishes `@elsa-workflows/elsa-studio-wasm` and `@elsa-workflows/elsa-studio-wasm-react` to Feedz from a 3.10.x prerelease tag. Stable Feedz publication waits for the 231-ID nuget.org promote guard. The npmjs.com upload is not in this job until trusted publishing is confirmed for `elsa-workflows/elsa-core`. Stable 3.10.x nuget.org publication is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)) (part of [#8725](https://github.com/elsa-workflows/elsa-core/issues/8725)). - The Apps container workflow lived in `elsa-apps` and core has no replacement yet. The container stage is blocked until it is re-homed in core. ## Interpret the request diff --git a/.agents/skills/elsa-release/references/runbook.md b/.agents/skills/elsa-release/references/runbook.md index 726fbd30f7..14516ec8e6 100644 --- a/.agents/skills/elsa-release/references/runbook.md +++ b/.agents/skills/elsa-release/references/runbook.md @@ -9,8 +9,8 @@ Studio, Extensions and Apps are folded into `elsa-core`; a release is one `elsa- What `elsa-core` actually does today (check `origin/main` before relying on it): - `.github/workflows/packages.yml` builds and uploads packages on `release: published` and on pushes to `main` and `release/*`. Those events never publish. Publication is an approved `workflow_dispatch`: `publish_preview_feedz` (Feedz, from a branch or a `3.10.x` prerelease tag) or `publish_nuget` (nuget.org, from a release-version tag). Stable `3.10.x` Feedz is owned only by `publish-consolidated-original-candidate.yml`. -- Its `./build.sh Compile+Pack` packs Core only. Stable `3.10.x` nuget.org publishing is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)). A `publish_nuget` dispatch on a stable `3.10.x` tag does not pack: it downloads the current pin (run/artifact `11412848210`), verifies each `.nupkg` sha256 against that candidate's seal, and runs `scripts/validate_packages_id_set.py` (231 IDs plus the three Studio ClientLib assets per package) before any push. The Oct 6 225-package set fails that guard. That pin's archive size and expiry (`2026-11-05T12:13:30Z`) come from `stable-original-envelope.json`; the replacement candidate's expiry is unknown until it is built. After the freeze, once the [3.10] picks and advisory fixes have landed, #9016 builds a fresh candidate from the `release/3.10.0` tip and re-pins it. `Elsa.SamplePackage` is not packable. The five `Elsa.Secrets.*` IDs and the four `Elsa.Studio.Host.*` IDs stay unpackable and `Elsa.Templates` is not in core. The whole-product 3.10.0 candidate is [prepared without publishing](#consolidated-3100-candidate-preparation-nonpublishing); `publish-consolidated-original-candidate.yml` is the only Feedz publisher for those stable 3.10.x bytes and runs the same 231-ID guard before its Feedz push (also blocked until re-pin (#9016)). -- `studio-npm-pair.yml` is a local proof of the two Studio npm archives. No core workflow publishes them. Stable 3.10.x nuget.org publication is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)) (part of [#8725](https://github.com/elsa-workflows/elsa-core/issues/8725)); npm publication remains pending. +- Its `./build.sh Compile+Pack` packs Core only on branch pushes and non-`3.10.0` tags. A `3.10.0` tag `release` event (and a non-promote dispatch from that tag) packs the 231-ID set through `prepare_consolidated_release_candidate.py`. Stable `3.10.x` nuget.org publishing is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)). A `publish_nuget` dispatch on a stable `3.10.x` tag does not pack: it downloads the current pin (run/artifact `11412848210`), verifies each `.nupkg` sha256 against that candidate's seal, and runs `scripts/validate_packages_id_set.py` (231 IDs plus the three Studio ClientLib assets per package) before any push. The Oct 6 225-package set fails that guard. That pin's archive size and expiry (`2026-11-05T12:13:30Z`) come from `stable-original-envelope.json`; the replacement candidate's expiry is unknown until it is built. After the freeze, once the [3.10] picks and advisory fixes have landed, #9016 builds a fresh candidate from the `release/3.10.0` tip and re-pins it. `Elsa.SamplePackage` is not packable. The five `Elsa.Secrets.*` IDs and the four `Elsa.Studio.Host.*` IDs stay unpackable and `Elsa.Templates` is not in core. The whole-product 3.10.0 candidate is [prepared without publishing](#consolidated-3100-candidate-preparation-nonpublishing); `publish-consolidated-original-candidate.yml` is the only Feedz publisher for those stable 3.10.x bytes and runs the same 231-ID guard before its Feedz push (also blocked until re-pin (#9016)). +- `studio-npm-pair.yml` is a local proof of the two Studio npm archives. `packages.yml` `publish_npm` publishes `@elsa-workflows/elsa-studio-wasm` and `@elsa-workflows/elsa-studio-wasm-react` to Feedz from a 3.10.x prerelease tag. The npmjs.com upload is not in this job until trusted publishing is confirmed for `elsa-workflows/elsa-core`. Stable `3.10.x` stays fail-closed until the 231-ID nuget.org promote guard can pass. The pair builder accepts 3.8–3.10 versions only. - Core has no container-image publishing workflow. The Apps workflow it used lived in `elsa-apps`. ## 1. Resolve the plan and preflight the Core and Templates repositories @@ -43,7 +43,7 @@ repository's `.github/workflows/packages.yml` actually reads: | Repository | Secrets read by `packages.yml` | Also confirm | | --- | --- | --- | -| `elsa-core` | `NUGET_USER` (nuget.org policy owner), `FEEDZ_API_KEY` | nuget.org Trusted Publishing policy for `packages.yml` | +| `elsa-core` | `NUGET_USER` (nuget.org policy owner), `FEEDZ_API_KEY`, `FEEDZ_API_KEY_BASE64` (Feedz npm) | nuget.org Trusted Publishing policy for `packages.yml` | | `elsa-templates` | `NUGET_USER`, `FEEDZ_API_KEY` | nuget.org policy | Never print or copy a secret value. The check stops on any API error rather diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 1f91724e1d..1487c329ae 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -13,6 +13,11 @@ on: required: true type: boolean default: false + publish_npm: + description: Publish the Studio npm pair to Feedz for this run (requires publisher approval). Live for 3.10.x prerelease tags. npmjs.com is not in this job until trusted publishing is confirmed. Stable 3.10.x stays fail-closed until the 231-ID nuget.org promote guard can pass. + required: true + type: boolean + default: false deploy_coverage: description: Deploy coverage to GitHub Pages for this run (requires deployment approval). required: true @@ -56,6 +61,7 @@ jobs: REF: ${{ github.ref }} PUBLISH_PREVIEW_FEEDZ: ${{ inputs.publish_preview_feedz }} PUBLISH_NUGET: ${{ inputs.publish_nuget }} + PUBLISH_NPM: ${{ inputs.publish_npm }} DEPLOY_COVERAGE: ${{ inputs.deploy_coverage }} run: python3 scripts/validate_packages_publication_selection.py @@ -313,7 +319,7 @@ jobs: - test_component - validate_publication_selection runs-on: ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 180 # Push and release events build as before; the selection check only runs on # manual dispatch, and a dispatch it rejects must not build. if: ${{ !cancelled() && github.event_name != 'pull_request' && needs.test_unit_integration.result == 'success' && needs.test_component.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.validate_publication_selection.result == 'success') }} @@ -372,12 +378,32 @@ jobs: - uses: actions/setup-dotnet@v4 if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }} with: - dotnet-version: 10.x + dotnet-version: | + 8.0.x + 9.0.x + 10.x + + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + if: ${{ (github.event_name == 'release' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/tags/3.10.0' && !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget) }} + with: + python-version: '3.12' - name: Compile+Pack - if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }} + if: ${{ !((github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) || ((github.event_name == 'release' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/tags/3.10.0')) }} run: ./build.sh Compile+Pack --version "${VERSION}" --analyseCode true + # --version 3.10.0 matches the refs/tags/3.10.0 guard above. The inventory + # baseline is per branch: this file on release/3.10.0 is this branch's + # evaluation. It is not main's inventory; the two are not the same. + - name: Pack consolidated 3.10.0 set + if: ${{ (github.event_name == 'release' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/tags/3.10.0' && !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget) }} + env: + PACKAGES_DIR: ${{ github.workspace }}/packages + run: | + set -euo pipefail + python3 scripts/integration-program/prepare_consolidated_release_candidate.py --version 3.10.0 --output "$RUNNER_TEMP/consolidated-candidate" --remote-sources + python3 scripts/validate_packages_id_set.py + - name: Upload artifact uses: actions/upload-artifact@v4 with: @@ -492,6 +518,120 @@ jobs: feed-source: ${{ env.nuget_feed_source }} api-key: ${{ steps.nuget_login.outputs.NUGET_API_KEY }} + build_npm: + name: Build Studio npm pair + needs: [build, validate_publication_selection] + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + PYTHONDONTWRITEBYTECODE: '1' + if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_npm && startsWith(github.ref, 'refs/tags/') }} + permissions: + contents: read + steps: + - name: Check out the Studio npm pair + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: '3.12' + + - uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 + with: + dotnet-version: '10.0.300' + + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: '22' + + - name: Build the Studio npm pair + run: | + set -euo pipefail + python3 scripts/integration-program/prove_studio_npm_pair.py \ + --commit "${GITHUB_SHA}" --version "${GITHUB_REF_NAME}" \ + --run-id "${GITHUB_RUN_ID}" --run-attempt "${GITHUB_RUN_ATTEMPT}" \ + --release-candidate --output "$RUNNER_TEMP/studio-npm-pair" + + - name: Upload Studio npm pair + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: studio-npm-pair + path: ${{ runner.temp }}/studio-npm-pair/retained/*.tgz + if-no-files-found: error + retention-days: 30 + + publish_npm: + name: Publish Studio npm pair + needs: [build_npm, validate_publication_selection] + runs-on: ubuntu-latest + timeout-minutes: 30 + if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_npm && startsWith(github.ref, 'refs/tags/') }} + permissions: + contents: read + steps: + - name: Fail closed on stable 3.10.x + if: ${{ startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-') }} + run: | + echo "Stable 3.10.x Studio npm pair stays fail-closed until the 231-ID nuget.org promote guard can pass." + exit 1 + + - name: Configure Feedz registry + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: '22' + registry-url: https://f.feedz.io/elsa-workflows/elsa-3/npm/ + + - name: Download Studio npm pair + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + with: + name: studio-npm-pair + path: ${{ runner.temp }}/studio-npm-pair + + - name: Verify Studio npm pair + run: | + set -euo pipefail + dir="$RUNNER_TEMP/studio-npm-pair" + wasm="elsa-workflows-elsa-studio-wasm-${GITHUB_REF_NAME}.tgz" + react="elsa-workflows-elsa-studio-wasm-react-${GITHUB_REF_NAME}.tgz" + test -f "$dir/$wasm" + test -f "$dir/$react" + count=$(find "$dir" -maxdepth 1 -name '*.tgz' | wc -l) + test "$count" -eq 2 + + - name: npm publish to Feedz + env: + NODE_AUTH_TOKEN: ${{ secrets.FEEDZ_API_KEY_BASE64 }} + run: | + set -euo pipefail + if [ -z "${NODE_AUTH_TOKEN:-}" ]; then + echo "::error::Feedz npm key resolved empty; nothing was published." + exit 1 + fi + status=0 + for file in "$RUNNER_TEMP"/studio-npm-pair/*.tgz + do + version=$(tar -xzOf "$file" package/package.json \ + | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>console.log(JSON.parse(s).version))") + case "$version" in + *-*) tag=next ;; + *) tag=latest ;; + esac + echo "Publishing $file ($version) with --tag $tag" + if output=$(npm publish "$file" --access public --tag "$tag" 2>&1); then + echo "$output" + else + echo "$output" + if echo "$output" | grep -qiE 'EPUBLISHCONFLICT|cannot publish over'; then + echo "::notice::$file is already published at this version - skipping" + else + status=1 + fi + fi + done + exit $status + deploy_coverage: name: Deploy coverage to GitHub Pages needs: [coverage_report, validate_publication_selection] diff --git a/.github/workflows/validate-packages-gates.yml b/.github/workflows/validate-packages-gates.yml index 7f74504404..fa720ae371 100644 --- a/.github/workflows/validate-packages-gates.yml +++ b/.github/workflows/validate-packages-gates.yml @@ -19,6 +19,8 @@ on: - 'scripts/integration-program/test_prepare_consolidated_release_candidate.py' - 'scripts/integration-program/consolidated-candidate-inventory-baseline.json' - 'scripts/integration-program/prove_consolidated*.py' + - 'scripts/integration-program/prove_studio_npm_pair.py' + - 'scripts/integration-program/test_prove_studio_npm_pair.py' - 'scripts/integration-program/test_prove_consolidated*.py' - 'scripts/integration-program/consolidated-package-consumer/**' - 'build/Build.cs' @@ -49,6 +51,8 @@ on: - 'scripts/integration-program/test_prepare_consolidated_release_candidate.py' - 'scripts/integration-program/consolidated-candidate-inventory-baseline.json' - 'scripts/integration-program/prove_consolidated*.py' + - 'scripts/integration-program/prove_studio_npm_pair.py' + - 'scripts/integration-program/test_prove_studio_npm_pair.py' - 'scripts/integration-program/test_prove_consolidated*.py' - 'scripts/integration-program/consolidated-package-consumer/**' - 'build/Build.cs' diff --git a/docs/integration-program/consolidation/package-publisher-gates.md b/docs/integration-program/consolidation/package-publisher-gates.md index d75b35bca6..921514a612 100644 --- a/docs/integration-program/consolidation/package-publisher-gates.md +++ b/docs/integration-program/consolidation/package-publisher-gates.md @@ -1,11 +1,14 @@ # Package and coverage publication gates -The Packages workflow now builds and tests normally on pushes and release events, but those events cannot publish packages or deploy coverage. The three publication jobs are default-off `workflow_dispatch` options: +The Packages workflow now builds and tests normally on pushes and release events, but those events cannot publish packages or deploy coverage. The four publication jobs are default-off `workflow_dispatch` options: - `publish_preview_feedz` publishes the run's packages to Feedz. Dispatch from a branch for a preview build (`-preview.`), or from a 3.10.x prerelease tag. Stable 3.10.x Feedz is owned only by `publish-consolidated-original-candidate.yml`. - `publish_nuget` publishes a release-tag package to NuGet.org. Dispatch from a release-version tag. Stable 3.10.x nuget.org publishing is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)): the job downloads the current pin (run/artifact `11412848210`), verifies each `.nupkg` sha256 against the candidate seal, and runs the 231-ID list and Studio content guards on that exact set before any push. The current 225-package set fails that guard. Other tags push this run's pack. +- `publish_npm` publishes `@elsa-workflows/elsa-studio-wasm` and `@elsa-workflows/elsa-studio-wasm-react` to Feedz. `build_npm` builds the pair without credentials. Dispatch from a release-version tag. Feedz npm is live for 3.10.x prerelease tags. The npmjs.com upload is not in this job until trusted publishing is confirmed for `elsa-workflows/elsa-core` (#8725). Stable 3.10.x is rejected in the selection check and also fail-closed in the job. The pair builder accepts 3.8–3.10 versions only, so a 3.11+ tag fails that check. - `deploy_coverage` deploys the coverage report to GitHub Pages. Dispatch from `main` or `release/3.6.1`, the refs whose coverage run uploads a Pages artifact. +A `3.10.0` tag `release` event (and a non-promote dispatch from that tag) packs through `prepare_consolidated_release_candidate.py` instead of Core-only `Compile+Pack`, then runs the 231-ID guard. The inventory baseline is per branch: `consolidated-candidate-inventory-baseline.json` on `release/3.10.0` is this branch's evaluation (231 packages / 135 exclusions). It is not main's inventory; the two are not the same. A dry-run of the Core-only path on `release/3.10.0` @ `ca7ac4ff` produced 109 IDs. + A tag dispatch accepts only release-version tags matching `^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z]+(\.[0-9A-Za-z]+)*)?$`, such as `3.8.4`, `3.8.0-rc2` or `3.10.0`. Tags such as `v3.10.0` or `test-1` are rejected whatever the options, and so is a 3.10 release spelled without the literal `3.10.` prefix (for example `03.10.0`). The tagged commit must also be contained in `main` or a `release/*` branch; the build checks this before packing. A stable 3.10.x nuget.org dispatch still runs this check but skips pack; publication of those bytes is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)). `3.10.1` and later cannot reach nuget.org or Feedz until a new pin exists. Each option defaults to `false`. An authorized operator should set only the option approved for that run; the workflow run records the selected ref and inputs. Package publication and coverage deployment remain separate decisions. Builds and uploaded package artifacts remain available without opting in when their event already uploads them; a manual dispatch uploads package artifacts only when a publisher option is selected. @@ -15,7 +18,7 @@ Each option defaults to `false`. An authorized operator should set only the opti | Trigger and ref | Selected options | Package build | Feedz | NuGet.org | Coverage to Pages | |---|---|---|---|---|---| | Push to `main` or `release/*` | none (inputs exist only on dispatch) | yes; artifact uploaded | no | no | no | -| Release published | none | yes, at the tag version; artifact uploaded | no | no | no | +| Release published | none | yes, at the tag version (`3.10.0` uses the 231-ID candidate pack); artifact uploaded | no | no | no | | Dispatch from any branch or release tag | none | yes; no artifact | no | no | no | | Dispatch from a branch | `publish_preview_feedz` | yes | preview version | no | no | | Dispatch from a release tag | `publish_nuget` | yes, at the tag version | no | tag version | no | @@ -24,6 +27,9 @@ Each option defaults to `false`. An authorized operator should set only the opti | Dispatch from a stable 3.10.0 tag | `publish_nuget` | no pack; retrieve + 231-ID guard (blocked until re-pin (#9016)) | no | blocked until re-pin (#9016) | no | | Dispatch from a later stable 3.10.x tag (`3.10.1`, …) | `publish_nuget` | no pack; pin is 3.10.0 only | no | blocked until a new pin | no | | Dispatch from `main` or `release/3.6.1` | `deploy_coverage` | yes | no | no | deployed | +| Dispatch from a 3.10.x prerelease tag | `publish_npm` | yes, at the tag version | Feedz npm | no | no | +| Dispatch from a stable 3.10.x tag | `publish_npm` | rejected | no | no | no | +| Dispatch from a 3.11+ tag | `publish_npm` | pair version check fails | no | no | no | | Dispatch from a branch | `publish_nuget` | rejected | no | no | no | | Dispatch from a release tag other than 3.10.x | `publish_preview_feedz` | rejected | no | no | no | | Dispatch from any other branch, or any tag | `deploy_coverage` | rejected | no | no | no | @@ -49,7 +55,7 @@ python3 -m unittest discover -s scripts -p 'test_validate_packages_*.py' The validator parses `packages.yml` and fails in these cases: -- Any job other than the three gated jobs references a Feedz or NuGet secret, the whole `secrets` context, `NuGet/login`, `actions/deploy-pages`, `dotnet nuget push`, the `push-nuget-packages` action, `id-token: write`, an `environment`, or reusable-workflow secrets. The same applies to workflow-level settings. +- Any job other than the four gated jobs references a Feedz or NuGet secret, the whole `secrets` context, `NuGet/login`, `actions/deploy-pages`, `dotnet nuget push`, the `push-nuget-packages` action, `npm publish`, `id-token: write`, an `environment`, or reusable-workflow secrets. The same applies to workflow-level settings. - A gated job does not need `validate_publication_selection`. - A gated job's `if:` does not require both a `workflow_dispatch` event and its own input as top-level conditions. - A gated job's `if:` calls a status function that would let it run after a failed selection check. @@ -60,7 +66,9 @@ The validator parses `packages.yml` and fails in these cases: - `publish_preview_feedz` accepts a stable `3.10.x` tag, or the selection check accepts Feedz for `3.10.0` / `3.10.1`. - `publish_nuget` does not retrieve the pinned candidate, stage it, and run the ID-set guard before NuGet login, those steps can continue on error, or the stage+guard `run:` is not exactly those two commands on separate lines. - `publish-consolidated-original-candidate.yml` does not run the same ID-set guard before its Feedz publish, or the guard step's `run:` is not exactly `set -euo pipefail`, stage, and the ID-set command on separate lines. A guard `shell:` or `defaults.run.shell` is rejected. -- `Compile+Pack` still runs on a stable 3.10.x nuget.org dispatch, or `packages.yml` packs `ConsolidatedReleaseCandidate` / builds Studio ClientLibs. +- `Compile+Pack` still runs on a stable 3.10.x nuget.org dispatch or a `3.10.0` tag pack, or `packages.yml` packs `ConsolidatedReleaseCandidate` / builds Studio ClientLibs instead of calling `prepare_consolidated_release_candidate.py`. +- `publish_npm` is missing, builds the pair itself, is not fail-closed on a stable 3.10.x tag, publishes to npmjs.com, or `validate_packages_id_set.txt` is not exactly 231 IDs. +- `build_npm` is missing, does not pin `setup-dotnet` to `10.0.300` at the `studio-npm-pair.yml` SHA, or `publish_npm` Feedz publish has no dist-tag / already-published handling. The tests mutate copies of the real workflow to confirm each of these cases is rejected. They also check every accepted and rejected dispatch selection. The nonpublishing `Validate package publication gates` workflow installs a hash-pinned PyYAML and runs the validator and tests on relevant PRs and main-branch changes. diff --git a/scripts/integration-program/consolidated-candidate-inventory-baseline.json b/scripts/integration-program/consolidated-candidate-inventory-baseline.json index 43686e9d83..fbbbb5b110 100644 --- a/scripts/integration-program/consolidated-candidate-inventory-baseline.json +++ b/scripts/integration-program/consolidated-candidate-inventory-baseline.json @@ -1,1536 +1,1614 @@ { "evidence": { - "archive_sha256": "8317e5766591f9da2d1f83cd6a85274bd41efbfbd0039d6a1bcfaf0c9bf81636", - "artifact_id": 11390805430, - "inventory_sha256": "5981ea53924127299dc165b9cee07de6450be9996c816249e2310cb987a2c6df", - "run_id": 37410240989, "scope": "Reviewed inventory comparison only; never relabel or reuse as candidate bytes.", - "source_commit": "44083dc4f47d56aa2d5c215b0c7479c0b7290cb0", - "version": "3.10.0-proof.37410240989.1" + "source_commit": "4c272d6f769c332b6974c7f39e61029b9bcc5726", + "version": "3.10.0", + "package_count": 231, + "exclusion_count": 135, + "issue": 8725, + "note": "release/3.10.0 evaluation only. This is not main's inventory; the two are not the same." }, "exclusions": [ { - "id": "_build", - "project": "build/_build.csproj", + "id": "Elsa.Server.Shared", + "project": "apps/src/Elsa.Server.Shared/Elsa.Server.Shared.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Server.Web", - "project": "samples/extensions/workbench/Elsa.Server.Web/Elsa.Server.Web.csproj", + "id": "Elsa.Server.Studio.BlazorServer", + "project": "apps/src/Elsa.Server.Studio.BlazorServer/Elsa.Server.Studio.BlazorServer.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.ServerAndStudio.Web", - "project": "samples/extensions/workbench/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj", + "id": "Elsa.Server.Studio.BlazorWasm.Client", + "project": "apps/src/Elsa.Server.Studio.BlazorWasm.Client/Elsa.Server.Studio.BlazorWasm.Client.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "ElsaStudioWebAssembly", - "project": "samples/extensions/workbench/ElsaStudioWebAssembly/ElsaStudioWebAssembly.csproj", + "id": "Elsa.Server.Studio.BlazorWasm", + "project": "apps/src/Elsa.Server.Studio.BlazorWasm/Elsa.Server.Studio.BlazorWasm.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "BlazorApp1", - "project": "samples/studio/BlazorApp1/BlazorApp1.csproj", + "id": "Elsa.Server", + "project": "apps/src/Elsa.Server/Elsa.Server.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.ModularServer.Web", - "project": "src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj", + "id": "Elsa.Studio.BlazorServer", + "project": "apps/src/Elsa.Studio.BlazorServer/Elsa.Studio.BlazorServer.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.SamplePackage", - "project": "src/apps/Elsa.SamplePackage/Elsa.SamplePackage.csproj", + "id": "Elsa.Studio.BlazorWasm.Client", + "project": "apps/src/Elsa.Studio.BlazorWasm.Client/Elsa.Studio.BlazorWasm.Client.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Server.LoadBalancer", - "project": "src/apps/Elsa.Server.LoadBalancer/Elsa.Server.LoadBalancer.csproj", + "id": "Elsa.Studio.BlazorWasm", + "project": "apps/src/Elsa.Studio.BlazorWasm/Elsa.Studio.BlazorWasm.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Server.Web", - "project": "src/apps/Elsa.Server.Web/Elsa.Server.Web.csproj", + "id": "Shared", + "project": "apps/src/Shared/Shared.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Secrets.Api", - "project": "src/extensions/secrets/Elsa.Secrets.Api/Elsa.Secrets.Api.csproj", + "id": "_build", + "project": "build/_build.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Secrets.Core", - "project": "src/extensions/secrets/Elsa.Secrets.Core/Elsa.Secrets.Core.csproj", + "id": "Elsa.ModularServer.Web", + "project": "core/src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Secrets.Management", - "project": "src/extensions/secrets/Elsa.Secrets.Management/Elsa.Secrets.Management.csproj", + "id": "Elsa.SamplePackage", + "project": "core/src/apps/Elsa.SamplePackage/Elsa.SamplePackage.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Secrets.Models", - "project": "src/extensions/secrets/Elsa.Secrets.Models/Elsa.Secrets.Models.csproj", + "id": "Elsa.Server.LoadBalancer", + "project": "core/src/apps/Elsa.Server.LoadBalancer/Elsa.Server.LoadBalancer.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Secrets.Scripting", - "project": "src/extensions/secrets/Elsa.Secrets.Scripting/Elsa.Secrets.Scripting.csproj", + "id": "Elsa.Server.Web", + "project": "core/src/apps/Elsa.Server.Web/Elsa.Server.Web.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Connections.Credentials.Persistence.EFCore.PostgreSql", - "project": "src/modules/Elsa.Connections.Credentials.Persistence.EFCore.PostgreSql/Elsa.Connections.Credentials.Persistence.EFCore.PostgreSql.csproj", + "id": "Elsa.Connections.Credentials.Persistence.EFCore.Sqlite", + "project": "core/src/modules/Elsa.Connections.Credentials.Persistence.EFCore.Sqlite/Elsa.Connections.Credentials.Persistence.EFCore.Sqlite.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Connections.Credentials.Persistence.EFCore.Sqlite", - "project": "src/modules/Elsa.Connections.Credentials.Persistence.EFCore.Sqlite/Elsa.Connections.Credentials.Persistence.EFCore.Sqlite.csproj", + "id": "Elsa.Workflows.ComponentTests", + "project": "core/test/component/Elsa.Workflows.ComponentTests/Elsa.Workflows.ComponentTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Connections.Credentials.Persistence.EFCore", - "project": "src/modules/Elsa.Connections.Credentials.Persistence.EFCore/Elsa.Connections.Credentials.Persistence.EFCore.csproj", + "id": "Elsa.AI.IntegrationTests", + "project": "core/test/integration/Elsa.AI.IntegrationTests/Elsa.AI.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Connections.Credentials.Workflows", - "project": "src/modules/Elsa.Connections.Credentials.Workflows/Elsa.Connections.Credentials.Workflows.csproj", + "id": "Elsa.Activities.IntegrationTests", + "project": "core/test/integration/Elsa.Activities.IntegrationTests/Elsa.Activities.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Connections", - "project": "src/modules/Elsa.Connections/Elsa.Connections.csproj", + "id": "Elsa.Alterations.IntegrationTests", + "project": "core/test/integration/Elsa.Alterations.IntegrationTests/Elsa.Alterations.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Core.Tests", - "project": "src/studio/framework/Elsa.Studio.Core.Tests/Elsa.Studio.Core.Tests.csproj", + "id": "Elsa.Alterations.Persistence.ConformanceTests", + "project": "core/test/integration/Elsa.Alterations.Persistence.ConformanceTests/Elsa.Alterations.Persistence.ConformanceTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Host.CustomElements", - "project": "src/studio/hosts/Elsa.Studio.Host.CustomElements/Elsa.Studio.Host.CustomElements.csproj", + "id": "Elsa.Bpmn.IntegrationTests", + "project": "core/test/integration/Elsa.Bpmn.IntegrationTests/Elsa.Bpmn.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Host.HostedWasm", - "project": "src/studio/hosts/Elsa.Studio.Host.HostedWasm/Elsa.Studio.Host.HostedWasm.csproj", + "id": "Elsa.Bpmn.Interchange.IntegrationTests", + "project": "core/test/integration/Elsa.Bpmn.Interchange.IntegrationTests/Elsa.Bpmn.Interchange.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Host.Server", - "project": "src/studio/hosts/Elsa.Studio.Host.Server/Elsa.Studio.Host.Server.csproj", + "id": "Elsa.Common.IntegrationTests", + "project": "core/test/integration/Elsa.Common.IntegrationTests/Elsa.Common.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Host.Wasm", - "project": "src/studio/hosts/Elsa.Studio.Host.Wasm/Elsa.Studio.Host.Wasm.csproj", + "id": "Elsa.Connections.Credentials.Persistence.PostgreSql.IntegrationTests", + "project": "core/test/integration/Elsa.Connections.Credentials.Persistence.PostgreSql.IntegrationTests/Elsa.Connections.Credentials.Persistence.PostgreSql.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.AI.Tests", - "project": "src/studio/modules/Elsa.Studio.AI.Tests/Elsa.Studio.AI.Tests.csproj", + "id": "Elsa.Diagnostics.ConsoleLogs.IntegrationTests", + "project": "core/test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/Elsa.Diagnostics.ConsoleLogs.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Administration.Tests", - "project": "src/studio/modules/Elsa.Studio.Administration.Tests/Elsa.Studio.Administration.Tests.csproj", + "id": "Elsa.Diagnostics.OpenTelemetry.IntegrationTests", + "project": "core/test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Authentication.UI.Tests", - "project": "src/studio/modules/Elsa.Studio.Authentication.UI.Tests/Elsa.Studio.Authentication.UI.Tests.csproj", + "id": "Elsa.Diagnostics.StructuredLogs.IntegrationTests", + "project": "core/test/integration/Elsa.Diagnostics.StructuredLogs.IntegrationTests/Elsa.Diagnostics.StructuredLogs.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Dashboard.Tests", - "project": "src/studio/modules/Elsa.Studio.Dashboard.Tests/Elsa.Studio.Dashboard.Tests.csproj", + "id": "Elsa.Diagnostics.StructuredLogs.Persistence.ConformanceTests", + "project": "core/test/integration/Elsa.Diagnostics.StructuredLogs.Persistence.ConformanceTests/Elsa.Diagnostics.StructuredLogs.Persistence.ConformanceTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Diagnostics.ConsoleLogs.Tests", - "project": "src/studio/modules/Elsa.Studio.Diagnostics.ConsoleLogs.Tests/Elsa.Studio.Diagnostics.ConsoleLogs.Tests.csproj", + "id": "Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests", + "project": "core/test/integration/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Diagnostics.OpenTelemetry.Tests", - "project": "src/studio/modules/Elsa.Studio.Diagnostics.OpenTelemetry.Tests/Elsa.Studio.Diagnostics.OpenTelemetry.Tests.csproj", + "id": "Elsa.Dsl.ElsaScript.IntegrationTests", + "project": "core/test/integration/Elsa.Dsl.ElsaScript.IntegrationTests/Elsa.Dsl.ElsaScript.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Diagnostics.StructuredLogs.Tests", - "project": "src/studio/modules/Elsa.Studio.Diagnostics.StructuredLogs.Tests/Elsa.Studio.Diagnostics.StructuredLogs.Tests.csproj", + "id": "Elsa.ExternalAuthentication.IntegrationTests", + "project": "core/test/integration/Elsa.ExternalAuthentication.IntegrationTests/Elsa.ExternalAuthentication.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Environments.Tests", - "project": "src/studio/modules/Elsa.Studio.Environments.Tests/Elsa.Studio.Environments.Tests.csproj", + "id": "Elsa.Hosts.SmokeTests", + "project": "core/test/integration/Elsa.Hosts.SmokeTests/Elsa.Hosts.SmokeTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.ExternalAuthentication.Tests", - "project": "src/studio/modules/Elsa.Studio.ExternalAuthentication.Tests/Elsa.Studio.ExternalAuthentication.Tests.csproj", + "id": "Elsa.Http.IntegrationTests", + "project": "core/test/integration/Elsa.Http.IntegrationTests/Elsa.Http.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Localization.Tests", - "project": "src/studio/modules/Elsa.Studio.Localization.Tests/Elsa.Studio.Localization.Tests.csproj", + "id": "Elsa.JavaScript.IntegrationTests", + "project": "core/test/integration/Elsa.JavaScript.IntegrationTests/Elsa.JavaScript.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.PlatformIntegration.Tests", - "project": "src/studio/modules/Elsa.Studio.PlatformIntegration.Tests/Elsa.Studio.PlatformIntegration.Tests.csproj", + "id": "Elsa.Labels.Persistence.ConformanceTests", + "project": "core/test/integration/Elsa.Labels.Persistence.ConformanceTests/Elsa.Labels.Persistence.ConformanceTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Secrets.Tests", - "project": "src/studio/modules/Elsa.Studio.Secrets.Tests/Elsa.Studio.Secrets.Tests.csproj", + "id": "Elsa.Resilience.IntegrationTests", + "project": "core/test/integration/Elsa.Resilience.IntegrationTests/Elsa.Resilience.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Security.Tests", - "project": "src/studio/modules/Elsa.Studio.Security.Tests/Elsa.Studio.Security.Tests.csproj", + "id": "Elsa.Secrets.Api.IntegrationTests", + "project": "core/test/integration/Elsa.Secrets.Api.IntegrationTests/Elsa.Secrets.Api.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.UserTasks.Tests", - "project": "src/studio/modules/Elsa.Studio.UserTasks.Tests/Elsa.Studio.UserTasks.Tests.csproj", + "id": "Elsa.Secrets.DefaultHost.IntegrationTests", + "project": "core/test/integration/Elsa.Secrets.DefaultHost.IntegrationTests/Elsa.Secrets.DefaultHost.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Workflows.Designer.Tests", - "project": "src/studio/modules/Elsa.Studio.Workflows.Designer.Tests/Elsa.Studio.Workflows.Designer.Tests.csproj", + "id": "Elsa.Workflows.IntegrationTests", + "project": "core/test/integration/Elsa.Workflows.IntegrationTests/Elsa.Workflows.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Workflows.Tests", - "project": "src/studio/modules/Elsa.Studio.Workflows.Tests/Elsa.Studio.Workflows.Tests.csproj", + "id": "Elsa.Workflows.Persistence.ConformanceTests", + "project": "core/test/integration/Elsa.Workflows.Persistence.ConformanceTests/Elsa.Workflows.Persistence.ConformanceTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Workflows.ComponentTests", - "project": "test/component/Elsa.Workflows.ComponentTests/Elsa.Workflows.ComponentTests.csproj", + "id": "Elsa.Workflows.PerformanceTests", + "project": "core/test/performance/Elsa.Workflows.PerformanceTests/Elsa.Workflows.PerformanceTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Actors.ProtoActor.UnitTests", - "project": "test/extensions/modules/actors/Elsa.Actors.ProtoActor.UnitTests/Elsa.Actors.ProtoActor.UnitTests.csproj", + "id": "Elsa.AI.Abstractions.UnitTests", + "project": "core/test/unit/Elsa.AI.Abstractions.UnitTests/Elsa.AI.Abstractions.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Studio.Agents.Tests", - "project": "test/extensions/modules/agents/Elsa.Studio.Agents.Tests/Elsa.Studio.Agents.Tests.csproj", + "id": "Elsa.AI.Copilot.UnitTests", + "project": "core/test/unit/Elsa.AI.Copilot.UnitTests/Elsa.AI.Copilot.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Caching.Distributed.ProtoActor.IntegrationTests", - "project": "test/extensions/modules/caching/Elsa.Caching.Distributed.ProtoActor.IntegrationTests/Elsa.Caching.Distributed.ProtoActor.IntegrationTests.csproj", + "id": "Elsa.AI.Host.UnitTests", + "project": "core/test/unit/Elsa.AI.Host.UnitTests/Elsa.AI.Host.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.DevOps.GitHub.UnitTests", - "project": "test/extensions/modules/devops/Elsa.DevOps.GitHub.UnitTests/Elsa.DevOps.GitHub.UnitTests.csproj", + "id": "Elsa.AI.Persistence.EFCore.UnitTests", + "project": "core/test/unit/Elsa.AI.Persistence.EFCore.UnitTests/Elsa.AI.Persistence.EFCore.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Logging.Core.IntegrationTests", - "project": "test/extensions/modules/diagnostics/Elsa.Logging.Core.IntegrationTests/Elsa.Logging.Core.IntegrationTests.csproj", + "id": "Elsa.Activities.UnitTests", + "project": "core/test/unit/Elsa.Activities.UnitTests/Elsa.Activities.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Logging.Core.UnitTests", - "project": "test/extensions/modules/diagnostics/Elsa.Logging.Core.UnitTests/Elsa.Logging.Core.UnitTests.csproj", + "id": "Elsa.Alterations.Core.UnitTests", + "project": "core/test/unit/Elsa.Alterations.Core.UnitTests/Elsa.Alterations.Core.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Ldap.UnitTests", - "project": "test/extensions/modules/ldap/Elsa.Ldap.UnitTests/Elsa.Ldap.UnitTests.csproj", + "id": "Elsa.Api.Common.UnitTests", + "project": "core/test/unit/Elsa.Api.Common.UnitTests/Elsa.Api.Common.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Mqtt.UnitTests", - "project": "test/extensions/modules/mqtt/Elsa.Mqtt.UnitTests/Elsa.Mqtt.UnitTests.csproj", + "id": "Elsa.Bpmn.Interchange.UnitTests", + "project": "core/test/unit/Elsa.Bpmn.Interchange.UnitTests/Elsa.Bpmn.Interchange.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Dapper.UnitTests", - "project": "test/extensions/modules/persistence/Elsa.Dapper.UnitTests/Elsa.Dapper.UnitTests.csproj", + "id": "Elsa.Bpmn.UnitTests", + "project": "core/test/unit/Elsa.Bpmn.UnitTests/Elsa.Bpmn.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.MongoDb.UnitTests", - "project": "test/extensions/modules/persistence/Elsa.MongoDb.UnitTests/Elsa.MongoDb.UnitTests.csproj", + "id": "Elsa.Common.UnitTests", + "project": "core/test/unit/Elsa.Common.UnitTests/Elsa.Common.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Persistence.Dapper.UnitTests", - "project": "test/extensions/modules/persistence/Elsa.Persistence.Dapper.UnitTests/Elsa.Persistence.Dapper.UnitTests.csproj", + "id": "Elsa.Connections.UnitTests", + "project": "core/test/unit/Elsa.Connections.UnitTests/Elsa.Connections.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Workflows.Runtime.ProtoActor.UnitTests", - "project": "test/extensions/modules/runtimes/Elsa.Workflows.Runtime.ProtoActor.UnitTests/Elsa.Workflows.Runtime.ProtoActor.UnitTests.csproj", + "id": "Elsa.Dashboard.Api.UnitTests", + "project": "core/test/unit/Elsa.Dashboard.Api.UnitTests/Elsa.Dashboard.Api.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Scheduling.Hangfire.UnitTests", - "project": "test/extensions/modules/scheduling/Elsa.Scheduling.Hangfire.UnitTests/Elsa.Scheduling.Hangfire.UnitTests.csproj", + "id": "Elsa.Diagnostics.ConsoleLogs.UnitTests", + "project": "core/test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/Elsa.Diagnostics.ConsoleLogs.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Scheduling.Quartz.ComponentTests", - "project": "test/extensions/modules/scheduling/Elsa.Scheduling.Quartz.ComponentTests/Elsa.Scheduling.Quartz.ComponentTests.csproj", + "id": "Elsa.Diagnostics.OpenTelemetry.UnitTests", + "project": "core/test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Scheduling.Quartz.UnitTests", - "project": "test/extensions/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/Elsa.Scheduling.Quartz.UnitTests.csproj", + "id": "Elsa.Diagnostics.StructuredLogs.Persistence.Relational.UnitTests", + "project": "core/test/unit/Elsa.Diagnostics.StructuredLogs.Persistence.Relational.UnitTests/Elsa.Diagnostics.StructuredLogs.Persistence.Relational.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Secrets.Management.UnitTests", - "project": "test/extensions/modules/secrets/Elsa.Secrets.Management.UnitTests/Elsa.Secrets.Management.UnitTests.csproj", + "id": "Elsa.Diagnostics.StructuredLogs.UnitTests", + "project": "core/test/unit/Elsa.Diagnostics.StructuredLogs.UnitTests/Elsa.Diagnostics.StructuredLogs.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.ServiceBus.AzureServiceBus.ComponentTests", - "project": "test/extensions/modules/servicebus/Elsa.ServiceBus.AzureServiceBus.ComponentTests/Elsa.ServiceBus.AzureServiceBus.ComponentTests.csproj", + "id": "Elsa.Expressions.UnitTests", + "project": "core/test/unit/Elsa.Expressions.UnitTests/Elsa.Expressions.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.ServiceBus.MassTransit.UnitTests", - "project": "test/extensions/modules/servicebus/Elsa.ServiceBus.MassTransit.UnitTests/Elsa.ServiceBus.MassTransit.UnitTests.csproj", + "id": "Elsa.ExternalAuthentication.UnitTests", + "project": "core/test/unit/Elsa.ExternalAuthentication.UnitTests/Elsa.ExternalAuthentication.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Slack.Tests", - "project": "test/extensions/modules/slack/Elsa.Slack.Tests/Elsa.Slack.Tests.csproj", + "id": "Elsa.Features.UnitTests", + "project": "core/test/unit/Elsa.Features.UnitTests/Elsa.Features.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.TestServer.Web", - "project": "test/extensions/workbench/Elsa.TestServer.Web/Elsa.TestServer.Web.csproj", + "id": "Elsa.Hosting.Management.UnitTests", + "project": "core/test/unit/Elsa.Hosting.Management.UnitTests/Elsa.Hosting.Management.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.AI.IntegrationTests", - "project": "test/integration/Elsa.AI.IntegrationTests/Elsa.AI.IntegrationTests.csproj", + "id": "Elsa.Http.UnitTests", + "project": "core/test/unit/Elsa.Http.UnitTests/Elsa.Http.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Activities.IntegrationTests", - "project": "test/integration/Elsa.Activities.IntegrationTests/Elsa.Activities.IntegrationTests.csproj", + "id": "Elsa.Identity.UnitTests", + "project": "core/test/unit/Elsa.Identity.UnitTests/Elsa.Identity.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Alterations.IntegrationTests", - "project": "test/integration/Elsa.Alterations.IntegrationTests/Elsa.Alterations.IntegrationTests.csproj", + "id": "Elsa.Labels.UnitTests", + "project": "core/test/unit/Elsa.Labels.UnitTests/Elsa.Labels.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Alterations.Persistence.ConformanceTests", - "project": "test/integration/Elsa.Alterations.Persistence.ConformanceTests/Elsa.Alterations.Persistence.ConformanceTests.csproj", + "id": "Elsa.Mediator.UnitTests", + "project": "core/test/unit/Elsa.Mediator.UnitTests/Elsa.Mediator.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Bpmn.IntegrationTests", - "project": "test/integration/Elsa.Bpmn.IntegrationTests/Elsa.Bpmn.IntegrationTests.csproj", + "id": "Elsa.Persistence.EFCore.MySql.UnitTests", + "project": "core/test/unit/Elsa.Persistence.EFCore.MySql.UnitTests/Elsa.Persistence.EFCore.MySql.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Bpmn.Interchange.IntegrationTests", - "project": "test/integration/Elsa.Bpmn.Interchange.IntegrationTests/Elsa.Bpmn.Interchange.IntegrationTests.csproj", + "id": "Elsa.Persistence.EFCore.UnitTests", + "project": "core/test/unit/Elsa.Persistence.EFCore.UnitTests/Elsa.Persistence.EFCore.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Common.IntegrationTests", - "project": "test/integration/Elsa.Common.IntegrationTests/Elsa.Common.IntegrationTests.csproj", + "id": "Elsa.Persistence.VNext.UnitTests", + "project": "core/test/unit/Elsa.Persistence.VNext.UnitTests/Elsa.Persistence.VNext.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Connections.Credentials.Persistence.PostgreSql.IntegrationTests", - "project": "test/integration/Elsa.Connections.Credentials.Persistence.PostgreSql.IntegrationTests/Elsa.Connections.Credentials.Persistence.PostgreSql.IntegrationTests.csproj", + "id": "Elsa.Platform.Integration.UnitTests", + "project": "core/test/unit/Elsa.Platform.Integration.UnitTests/Elsa.Platform.Integration.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Diagnostics.ConsoleLogs.IntegrationTests", - "project": "test/integration/Elsa.Diagnostics.ConsoleLogs.IntegrationTests/Elsa.Diagnostics.ConsoleLogs.IntegrationTests.csproj", + "id": "Elsa.Resilience.Core.UnitTests", + "project": "core/test/unit/Elsa.Resilience.Core.UnitTests/Elsa.Resilience.Core.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Diagnostics.OpenTelemetry.IntegrationTests", - "project": "test/integration/Elsa.Diagnostics.OpenTelemetry.IntegrationTests/Elsa.Diagnostics.OpenTelemetry.IntegrationTests.csproj", + "id": "Elsa.SasTokens.UnitTests", + "project": "core/test/unit/Elsa.SasTokens.UnitTests/Elsa.SasTokens.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Diagnostics.StructuredLogs.IntegrationTests", - "project": "test/integration/Elsa.Diagnostics.StructuredLogs.IntegrationTests/Elsa.Diagnostics.StructuredLogs.IntegrationTests.csproj", + "id": "Elsa.Scheduling.UnitTests", + "project": "core/test/unit/Elsa.Scheduling.UnitTests/Elsa.Scheduling.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Diagnostics.StructuredLogs.Persistence.ConformanceTests", - "project": "test/integration/Elsa.Diagnostics.StructuredLogs.Persistence.ConformanceTests/Elsa.Diagnostics.StructuredLogs.Persistence.ConformanceTests.csproj", + "id": "Elsa.Secrets.UnitTests", + "project": "core/test/unit/Elsa.Secrets.UnitTests/Elsa.Secrets.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests", - "project": "test/integration/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.IntegrationTests.csproj", + "id": "Elsa.Shells.Api.Tests", + "project": "core/test/unit/Elsa.Shells.Api.Tests/Elsa.Shells.Api.Tests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Dsl.ElsaScript.IntegrationTests", - "project": "test/integration/Elsa.Dsl.ElsaScript.IntegrationTests/Elsa.Dsl.ElsaScript.IntegrationTests.csproj", + "id": "Elsa.Tenants.UnitTests", + "project": "core/test/unit/Elsa.Tenants.UnitTests/Elsa.Tenants.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.ExternalAuthentication.IntegrationTests", - "project": "test/integration/Elsa.ExternalAuthentication.IntegrationTests/Elsa.ExternalAuthentication.IntegrationTests.csproj", + "id": "Elsa.UserTasks.Persistence.ConformanceTests", + "project": "core/test/unit/Elsa.UserTasks.Persistence.ConformanceTests/Elsa.UserTasks.Persistence.ConformanceTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Hosts.SmokeTests", - "project": "test/integration/Elsa.Hosts.SmokeTests/Elsa.Hosts.SmokeTests.csproj", + "id": "Elsa.UserTasks.Persistence.EFCore.UnitTests", + "project": "core/test/unit/Elsa.UserTasks.Persistence.EFCore.UnitTests/Elsa.UserTasks.Persistence.EFCore.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Http.IntegrationTests", - "project": "test/integration/Elsa.Http.IntegrationTests/Elsa.Http.IntegrationTests.csproj", + "id": "Elsa.UserTasks.UnitTests", + "project": "core/test/unit/Elsa.UserTasks.UnitTests/Elsa.UserTasks.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.JavaScript.IntegrationTests", - "project": "test/integration/Elsa.JavaScript.IntegrationTests/Elsa.JavaScript.IntegrationTests.csproj", + "id": "Elsa.Workflows.Api.UnitTests", + "project": "core/test/unit/Elsa.Workflows.Api.UnitTests/Elsa.Workflows.Api.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Labels.Persistence.ConformanceTests", - "project": "test/integration/Elsa.Labels.Persistence.ConformanceTests/Elsa.Labels.Persistence.ConformanceTests.csproj", + "id": "Elsa.Workflows.Core.UnitTests", + "project": "core/test/unit/Elsa.Workflows.Core.UnitTests/Elsa.Workflows.Core.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Resilience.IntegrationTests", - "project": "test/integration/Elsa.Resilience.IntegrationTests/Elsa.Resilience.IntegrationTests.csproj", + "id": "Elsa.Workflows.Management.UnitTests", + "project": "core/test/unit/Elsa.Workflows.Management.UnitTests/Elsa.Workflows.Management.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Secrets.Api.IntegrationTests", - "project": "test/integration/Elsa.Secrets.Api.IntegrationTests/Elsa.Secrets.Api.IntegrationTests.csproj", + "id": "Elsa.Workflows.Runtime.UnitTests", + "project": "core/test/unit/Elsa.Workflows.Runtime.UnitTests/Elsa.Workflows.Runtime.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Secrets.DefaultHost.IntegrationTests", - "project": "test/integration/Elsa.Secrets.DefaultHost.IntegrationTests/Elsa.Secrets.DefaultHost.IntegrationTests.csproj", + "id": "Elsa.Connections.Credentials.WorkerProcess", + "project": "core/test/workers/Elsa.Connections.Credentials.WorkerProcess/Elsa.Connections.Credentials.WorkerProcess.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Workflows.IntegrationTests", - "project": "test/integration/Elsa.Workflows.IntegrationTests/Elsa.Workflows.IntegrationTests.csproj", + "id": "Elsa.Workflows.Admission.WorkerProcess", + "project": "core/test/workers/Elsa.Workflows.Admission.WorkerProcess/Elsa.Workflows.Admission.WorkerProcess.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Workflows.Persistence.ConformanceTests", - "project": "test/integration/Elsa.Workflows.Persistence.ConformanceTests/Elsa.Workflows.Persistence.ConformanceTests.csproj", + "id": "Elsa.Server.Web", + "project": "extensions/samples/workbench/Elsa.Server.Web/Elsa.Server.Web.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Workflows.PerformanceTests", - "project": "test/performance/Elsa.Workflows.PerformanceTests/Elsa.Workflows.PerformanceTests.csproj", + "id": "Elsa.ServerAndStudio.Web", + "project": "extensions/samples/workbench/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.AI.Abstractions.UnitTests", - "project": "test/unit/Elsa.AI.Abstractions.UnitTests/Elsa.AI.Abstractions.UnitTests.csproj", + "id": "ElsaStudioWebAssembly", + "project": "extensions/samples/workbench/ElsaStudioWebAssembly/ElsaStudioWebAssembly.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.AI.Copilot.UnitTests", - "project": "test/unit/Elsa.AI.Copilot.UnitTests/Elsa.AI.Copilot.UnitTests.csproj", + "id": "Elsa.Secrets.Api", + "project": "extensions/src/secrets/Elsa.Secrets.Api/Elsa.Secrets.Api.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.AI.Host.UnitTests", - "project": "test/unit/Elsa.AI.Host.UnitTests/Elsa.AI.Host.UnitTests.csproj", + "id": "Elsa.Secrets.Core", + "project": "extensions/src/secrets/Elsa.Secrets.Core/Elsa.Secrets.Core.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.AI.Persistence.EFCore.UnitTests", - "project": "test/unit/Elsa.AI.Persistence.EFCore.UnitTests/Elsa.AI.Persistence.EFCore.UnitTests.csproj", + "id": "Elsa.Secrets.Management", + "project": "extensions/src/secrets/Elsa.Secrets.Management/Elsa.Secrets.Management.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Activities.UnitTests", - "project": "test/unit/Elsa.Activities.UnitTests/Elsa.Activities.UnitTests.csproj", + "id": "Elsa.Secrets.Models", + "project": "extensions/src/secrets/Elsa.Secrets.Models/Elsa.Secrets.Models.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Alterations.Core.UnitTests", - "project": "test/unit/Elsa.Alterations.Core.UnitTests/Elsa.Alterations.Core.UnitTests.csproj", + "id": "Elsa.Secrets.Scripting", + "project": "extensions/src/secrets/Elsa.Secrets.Scripting/Elsa.Secrets.Scripting.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Api.Common.UnitTests", - "project": "test/unit/Elsa.Api.Common.UnitTests/Elsa.Api.Common.UnitTests.csproj", + "id": "Elsa.Actors.ProtoActor.UnitTests", + "project": "extensions/test/modules/actors/Elsa.Actors.ProtoActor.UnitTests/Elsa.Actors.ProtoActor.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Bpmn.Interchange.UnitTests", - "project": "test/unit/Elsa.Bpmn.Interchange.UnitTests/Elsa.Bpmn.Interchange.UnitTests.csproj", + "id": "Elsa.Agents.Core.UnitTests", + "project": "extensions/test/modules/agents/Elsa.Agents.Core.UnitTests/Elsa.Agents.Core.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Bpmn.UnitTests", - "project": "test/unit/Elsa.Bpmn.UnitTests/Elsa.Bpmn.UnitTests.csproj", + "id": "Elsa.Studio.Agents.Tests", + "project": "extensions/test/modules/agents/Elsa.Studio.Agents.Tests/Elsa.Studio.Agents.Tests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Common.UnitTests", - "project": "test/unit/Elsa.Common.UnitTests/Elsa.Common.UnitTests.csproj", + "id": "Elsa.Caching.Distributed.ProtoActor.IntegrationTests", + "project": "extensions/test/modules/caching/Elsa.Caching.Distributed.ProtoActor.IntegrationTests/Elsa.Caching.Distributed.ProtoActor.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Connections.UnitTests", - "project": "test/unit/Elsa.Connections.UnitTests/Elsa.Connections.UnitTests.csproj", + "id": "Elsa.DevOps.GitHub.UnitTests", + "project": "extensions/test/modules/devops/Elsa.DevOps.GitHub.UnitTests/Elsa.DevOps.GitHub.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Dashboard.Api.UnitTests", - "project": "test/unit/Elsa.Dashboard.Api.UnitTests/Elsa.Dashboard.Api.UnitTests.csproj", + "id": "Elsa.Logging.Core.IntegrationTests", + "project": "extensions/test/modules/diagnostics/Elsa.Logging.Core.IntegrationTests/Elsa.Logging.Core.IntegrationTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Diagnostics.ConsoleLogs.UnitTests", - "project": "test/unit/Elsa.Diagnostics.ConsoleLogs.UnitTests/Elsa.Diagnostics.ConsoleLogs.UnitTests.csproj", + "id": "Elsa.Logging.Core.UnitTests", + "project": "extensions/test/modules/diagnostics/Elsa.Logging.Core.UnitTests/Elsa.Logging.Core.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Diagnostics.OpenTelemetry.UnitTests", - "project": "test/unit/Elsa.Diagnostics.OpenTelemetry.UnitTests/Elsa.Diagnostics.OpenTelemetry.UnitTests.csproj", + "id": "Elsa.Ldap.UnitTests", + "project": "extensions/test/modules/ldap/Elsa.Ldap.UnitTests/Elsa.Ldap.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Diagnostics.StructuredLogs.Persistence.Relational.UnitTests", - "project": "test/unit/Elsa.Diagnostics.StructuredLogs.Persistence.Relational.UnitTests/Elsa.Diagnostics.StructuredLogs.Persistence.Relational.UnitTests.csproj", + "id": "Elsa.Mqtt.UnitTests", + "project": "extensions/test/modules/mqtt/Elsa.Mqtt.UnitTests/Elsa.Mqtt.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Diagnostics.StructuredLogs.UnitTests", - "project": "test/unit/Elsa.Diagnostics.StructuredLogs.UnitTests/Elsa.Diagnostics.StructuredLogs.UnitTests.csproj", + "id": "Elsa.Dapper.UnitTests", + "project": "extensions/test/modules/persistence/Elsa.Dapper.UnitTests/Elsa.Dapper.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Expressions.UnitTests", - "project": "test/unit/Elsa.Expressions.UnitTests/Elsa.Expressions.UnitTests.csproj", + "id": "Elsa.MongoDb.UnitTests", + "project": "extensions/test/modules/persistence/Elsa.MongoDb.UnitTests/Elsa.MongoDb.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.ExternalAuthentication.UnitTests", - "project": "test/unit/Elsa.ExternalAuthentication.UnitTests/Elsa.ExternalAuthentication.UnitTests.csproj", + "id": "Elsa.Persistence.Dapper.UnitTests", + "project": "extensions/test/modules/persistence/Elsa.Persistence.Dapper.UnitTests/Elsa.Persistence.Dapper.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Features.UnitTests", - "project": "test/unit/Elsa.Features.UnitTests/Elsa.Features.UnitTests.csproj", + "id": "Elsa.Workflows.Runtime.ProtoActor.UnitTests", + "project": "extensions/test/modules/runtimes/Elsa.Workflows.Runtime.ProtoActor.UnitTests/Elsa.Workflows.Runtime.ProtoActor.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Hosting.Management.UnitTests", - "project": "test/unit/Elsa.Hosting.Management.UnitTests/Elsa.Hosting.Management.UnitTests.csproj", + "id": "Elsa.Scheduling.Hangfire.UnitTests", + "project": "extensions/test/modules/scheduling/Elsa.Scheduling.Hangfire.UnitTests/Elsa.Scheduling.Hangfire.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Http.UnitTests", - "project": "test/unit/Elsa.Http.UnitTests/Elsa.Http.UnitTests.csproj", + "id": "Elsa.Scheduling.Quartz.ComponentTests", + "project": "extensions/test/modules/scheduling/Elsa.Scheduling.Quartz.ComponentTests/Elsa.Scheduling.Quartz.ComponentTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Identity.UnitTests", - "project": "test/unit/Elsa.Identity.UnitTests/Elsa.Identity.UnitTests.csproj", + "id": "Elsa.Scheduling.Quartz.UnitTests", + "project": "extensions/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/Elsa.Scheduling.Quartz.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Labels.UnitTests", - "project": "test/unit/Elsa.Labels.UnitTests/Elsa.Labels.UnitTests.csproj", + "id": "Elsa.Secrets.Management.UnitTests", + "project": "extensions/test/modules/secrets/Elsa.Secrets.Management.UnitTests/Elsa.Secrets.Management.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Persistence.EFCore.UnitTests", - "project": "test/unit/Elsa.Persistence.EFCore.UnitTests/Elsa.Persistence.EFCore.UnitTests.csproj", + "id": "Elsa.ServiceBus.AzureServiceBus.ComponentTests", + "project": "extensions/test/modules/servicebus/Elsa.ServiceBus.AzureServiceBus.ComponentTests/Elsa.ServiceBus.AzureServiceBus.ComponentTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Persistence.VNext.UnitTests", - "project": "test/unit/Elsa.Persistence.VNext.UnitTests/Elsa.Persistence.VNext.UnitTests.csproj", + "id": "Elsa.ServiceBus.MassTransit.UnitTests", + "project": "extensions/test/modules/servicebus/Elsa.ServiceBus.MassTransit.UnitTests/Elsa.ServiceBus.MassTransit.UnitTests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Platform.Integration.UnitTests", - "project": "test/unit/Elsa.Platform.Integration.UnitTests/Elsa.Platform.Integration.UnitTests.csproj", + "id": "Elsa.Slack.Tests", + "project": "extensions/test/modules/slack/Elsa.Slack.Tests/Elsa.Slack.Tests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Resilience.Core.UnitTests", - "project": "test/unit/Elsa.Resilience.Core.UnitTests/Elsa.Resilience.Core.UnitTests.csproj", + "id": "Elsa.TestServer.Web", + "project": "extensions/test/workbench/Elsa.TestServer.Web/Elsa.TestServer.Web.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.SasTokens.UnitTests", - "project": "test/unit/Elsa.SasTokens.UnitTests/Elsa.SasTokens.UnitTests.csproj", + "id": "BlazorApp1", + "project": "studio/samples/BlazorApp1/BlazorApp1.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Scheduling.UnitTests", - "project": "test/unit/Elsa.Scheduling.UnitTests/Elsa.Scheduling.UnitTests.csproj", + "id": "Elsa.Studio.Core.Tests", + "project": "studio/src/framework/Elsa.Studio.Core.Tests/Elsa.Studio.Core.Tests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Secrets.UnitTests", - "project": "test/unit/Elsa.Secrets.UnitTests/Elsa.Secrets.UnitTests.csproj", + "id": "Elsa.Studio.Host.CustomElements", + "project": "studio/src/hosts/Elsa.Studio.Host.CustomElements/Elsa.Studio.Host.CustomElements.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Shells.Api.Tests", - "project": "test/unit/Elsa.Shells.Api.Tests/Elsa.Shells.Api.Tests.csproj", + "id": "Elsa.Studio.Host.HostedWasm", + "project": "studio/src/hosts/Elsa.Studio.Host.HostedWasm/Elsa.Studio.Host.HostedWasm.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Tenants.UnitTests", - "project": "test/unit/Elsa.Tenants.UnitTests/Elsa.Tenants.UnitTests.csproj", + "id": "Elsa.Studio.Host.Server", + "project": "studio/src/hosts/Elsa.Studio.Host.Server/Elsa.Studio.Host.Server.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.UserTasks.Persistence.ConformanceTests", - "project": "test/unit/Elsa.UserTasks.Persistence.ConformanceTests/Elsa.UserTasks.Persistence.ConformanceTests.csproj", + "id": "Elsa.Studio.Host.Wasm", + "project": "studio/src/hosts/Elsa.Studio.Host.Wasm/Elsa.Studio.Host.Wasm.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.UserTasks.Persistence.EFCore.UnitTests", - "project": "test/unit/Elsa.UserTasks.Persistence.EFCore.UnitTests/Elsa.UserTasks.Persistence.EFCore.UnitTests.csproj", + "id": "Elsa.Studio.AI.Tests", + "project": "studio/src/modules/Elsa.Studio.AI.Tests/Elsa.Studio.AI.Tests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.UserTasks.UnitTests", - "project": "test/unit/Elsa.UserTasks.UnitTests/Elsa.UserTasks.UnitTests.csproj", + "id": "Elsa.Studio.Administration.Tests", + "project": "studio/src/modules/Elsa.Studio.Administration.Tests/Elsa.Studio.Administration.Tests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Workflows.Api.UnitTests", - "project": "test/unit/Elsa.Workflows.Api.UnitTests/Elsa.Workflows.Api.UnitTests.csproj", + "id": "Elsa.Studio.Authentication.UI.Tests", + "project": "studio/src/modules/Elsa.Studio.Authentication.UI.Tests/Elsa.Studio.Authentication.UI.Tests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Workflows.Core.UnitTests", - "project": "test/unit/Elsa.Workflows.Core.UnitTests/Elsa.Workflows.Core.UnitTests.csproj", + "id": "Elsa.Studio.Dashboard.Tests", + "project": "studio/src/modules/Elsa.Studio.Dashboard.Tests/Elsa.Studio.Dashboard.Tests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Workflows.Management.UnitTests", - "project": "test/unit/Elsa.Workflows.Management.UnitTests/Elsa.Workflows.Management.UnitTests.csproj", + "id": "Elsa.Studio.Diagnostics.ConsoleLogs.Tests", + "project": "studio/src/modules/Elsa.Studio.Diagnostics.ConsoleLogs.Tests/Elsa.Studio.Diagnostics.ConsoleLogs.Tests.csproj", "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Workflows.Runtime.UnitTests", - "project": "test/unit/Elsa.Workflows.Runtime.UnitTests/Elsa.Workflows.Runtime.UnitTests.csproj", + "id": "Elsa.Studio.Diagnostics.OpenTelemetry.Tests", + "project": "studio/src/modules/Elsa.Studio.Diagnostics.OpenTelemetry.Tests/Elsa.Studio.Diagnostics.OpenTelemetry.Tests.csproj", "reason": "Project or inherited nonpackable setting remains active" - } - ], - "packages": [ - { - "id": "Elsa.Api.Client", - "project": "src/clients/Elsa.Api.Client/Elsa.Api.Client.csproj" }, { - "id": "Elsa.Api.Common", - "project": "src/common/Elsa.Api.Common/Elsa.Api.Common.csproj" + "id": "Elsa.Studio.Diagnostics.StructuredLogs.Tests", + "project": "studio/src/modules/Elsa.Studio.Diagnostics.StructuredLogs.Tests/Elsa.Studio.Diagnostics.StructuredLogs.Tests.csproj", + "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Features", - "project": "src/common/Elsa.Features/Elsa.Features.csproj" + "id": "Elsa.Studio.Environments.Tests", + "project": "studio/src/modules/Elsa.Studio.Environments.Tests/Elsa.Studio.Environments.Tests.csproj", + "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Mediator", - "project": "src/common/Elsa.Mediator/Elsa.Mediator.csproj" + "id": "Elsa.Studio.ExternalAuthentication.Tests", + "project": "studio/src/modules/Elsa.Studio.ExternalAuthentication.Tests/Elsa.Studio.ExternalAuthentication.Tests.csproj", + "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Testing.Shared.Component", - "project": "src/common/Elsa.Testing.Shared.Component/Elsa.Testing.Shared.Component.csproj" + "id": "Elsa.Studio.Localization.Tests", + "project": "studio/src/modules/Elsa.Studio.Localization.Tests/Elsa.Studio.Localization.Tests.csproj", + "reason": "Project or inherited nonpackable setting remains active" }, { - "id": "Elsa.Testing.Shared.Integration", - "project": "src/common/Elsa.Testing.Shared.Integration/Elsa.Testing.Shared.Integration.csproj" + "id": "Elsa.Studio.PlatformIntegration.Tests", + "project": "studio/src/modules/Elsa.Studio.PlatformIntegration.Tests/Elsa.Studio.PlatformIntegration.Tests.csproj", + "reason": "Project or inherited nonpackable setting remains active" + }, + { + "id": "Elsa.Studio.Secrets.Tests", + "project": "studio/src/modules/Elsa.Studio.Secrets.Tests/Elsa.Studio.Secrets.Tests.csproj", + "reason": "Project or inherited nonpackable setting remains active" + }, + { + "id": "Elsa.Studio.Security.Tests", + "project": "studio/src/modules/Elsa.Studio.Security.Tests/Elsa.Studio.Security.Tests.csproj", + "reason": "Project or inherited nonpackable setting remains active" + }, + { + "id": "Elsa.Studio.UserTasks.Tests", + "project": "studio/src/modules/Elsa.Studio.UserTasks.Tests/Elsa.Studio.UserTasks.Tests.csproj", + "reason": "Project or inherited nonpackable setting remains active" + }, + { + "id": "Elsa.Studio.Workflows.Designer.Tests", + "project": "studio/src/modules/Elsa.Studio.Workflows.Designer.Tests/Elsa.Studio.Workflows.Designer.Tests.csproj", + "reason": "Project or inherited nonpackable setting remains active" + }, + { + "id": "Elsa.Studio.Workflows.Tests", + "project": "studio/src/modules/Elsa.Studio.Workflows.Tests/Elsa.Studio.Workflows.Tests.csproj", + "reason": "Project or inherited nonpackable setting remains active" + } + ], + "packages": [ + { + "id": "Elsa.Api.Client", + "project": "core/src/clients/Elsa.Api.Client/Elsa.Api.Client.csproj" + }, + { + "id": "Elsa.Api.Common", + "project": "core/src/common/Elsa.Api.Common/Elsa.Api.Common.csproj" + }, + { + "id": "Elsa.Features", + "project": "core/src/common/Elsa.Features/Elsa.Features.csproj" + }, + { + "id": "Elsa.Mediator", + "project": "core/src/common/Elsa.Mediator/Elsa.Mediator.csproj" + }, + { + "id": "Elsa.Testing.Shared.Component", + "project": "core/src/common/Elsa.Testing.Shared.Component/Elsa.Testing.Shared.Component.csproj" + }, + { + "id": "Elsa.Testing.Shared.Integration", + "project": "core/src/common/Elsa.Testing.Shared.Integration/Elsa.Testing.Shared.Integration.csproj" }, { "id": "Elsa.Testing.Shared", - "project": "src/common/Elsa.Testing.Shared/Elsa.Testing.Shared.csproj" + "project": "core/src/common/Elsa.Testing.Shared/Elsa.Testing.Shared.csproj" }, { - "id": "Elsa.Actors.ProtoActor.PubSub.Redis", - "project": "src/extensions/actors/Elsa.Actors.ProtoActor.PubSub.Redis/Elsa.Actors.ProtoActor.PubSub.Redis.csproj" + "id": "Elsa.AI.Abstractions", + "project": "core/src/modules/Elsa.AI.Abstractions/Elsa.AI.Abstractions.csproj" }, { - "id": "Elsa.Actors.ProtoActor", - "project": "src/extensions/actors/Elsa.Actors.ProtoActor/Elsa.Actors.ProtoActor.csproj" + "id": "Elsa.AI.Copilot", + "project": "core/src/modules/Elsa.AI.Copilot/Elsa.AI.Copilot.csproj" }, { - "id": "Elsa.Agents.Activities", - "project": "src/extensions/agents/Elsa.Agents.Activities/Elsa.Agents.Activities.csproj" + "id": "Elsa.AI.Host", + "project": "core/src/modules/Elsa.AI.Host/Elsa.AI.Host.csproj" }, { - "id": "Elsa.Agents.Api", - "project": "src/extensions/agents/Elsa.Agents.Api/Elsa.Agents.Api.csproj" + "id": "Elsa.AI.Persistence.EFCore.MySql", + "project": "core/src/modules/Elsa.AI.Persistence.EFCore.MySql/Elsa.AI.Persistence.EFCore.MySql.csproj" }, { - "id": "Elsa.Agents.AzureOpenAI", - "project": "src/extensions/agents/Elsa.Agents.AzureOpenAI/Elsa.Agents.AzureOpenAI.csproj" + "id": "Elsa.AI.Persistence.EFCore.Oracle", + "project": "core/src/modules/Elsa.AI.Persistence.EFCore.Oracle/Elsa.AI.Persistence.EFCore.Oracle.csproj" }, { - "id": "Elsa.Agents.Core", - "project": "src/extensions/agents/Elsa.Agents.Core/Elsa.Agents.Core.csproj" + "id": "Elsa.AI.Persistence.EFCore.PostgreSql", + "project": "core/src/modules/Elsa.AI.Persistence.EFCore.PostgreSql/Elsa.AI.Persistence.EFCore.PostgreSql.csproj" }, { - "id": "Elsa.Agents.Models", - "project": "src/extensions/agents/Elsa.Agents.Models/Elsa.Agents.Models.csproj" + "id": "Elsa.AI.Persistence.EFCore.SqlServer", + "project": "core/src/modules/Elsa.AI.Persistence.EFCore.SqlServer/Elsa.AI.Persistence.EFCore.SqlServer.csproj" }, { - "id": "Elsa.Agents.OpenAI", - "project": "src/extensions/agents/Elsa.Agents.OpenAI/Elsa.Agents.OpenAI.csproj" + "id": "Elsa.AI.Persistence.EFCore.Sqlite", + "project": "core/src/modules/Elsa.AI.Persistence.EFCore.Sqlite/Elsa.AI.Persistence.EFCore.Sqlite.csproj" }, { - "id": "Elsa.Agents.Persistence.EFCore.MySql", - "project": "src/extensions/agents/Elsa.Agents.Persistence.EFCore.MySql/Elsa.Agents.Persistence.EFCore.MySql.csproj" + "id": "Elsa.AI.Persistence.EFCore", + "project": "core/src/modules/Elsa.AI.Persistence.EFCore/Elsa.AI.Persistence.EFCore.csproj" }, { - "id": "Elsa.Agents.Persistence.EFCore.PostgreSql", - "project": "src/extensions/agents/Elsa.Agents.Persistence.EFCore.PostgreSql/Elsa.Agents.Persistence.EFCore.PostgreSql.csproj" + "id": "Elsa.Alterations.Core", + "project": "core/src/modules/Elsa.Alterations.Core/Elsa.Alterations.Core.csproj" }, { - "id": "Elsa.Agents.Persistence.EFCore.SqlServer", - "project": "src/extensions/agents/Elsa.Agents.Persistence.EFCore.SqlServer/Elsa.Agents.Persistence.EFCore.SqlServer.csproj" + "id": "Elsa.Alterations", + "project": "core/src/modules/Elsa.Alterations/Elsa.Alterations.csproj" }, { - "id": "Elsa.Agents.Persistence.EFCore.Sqlite", - "project": "src/extensions/agents/Elsa.Agents.Persistence.EFCore.Sqlite/Elsa.Agents.Persistence.EFCore.Sqlite.csproj" + "id": "Elsa.Bpmn.Interchange", + "project": "core/src/modules/Elsa.Bpmn.Interchange/Elsa.Bpmn.Interchange.csproj" }, { - "id": "Elsa.Agents.Persistence.EFCore", - "project": "src/extensions/agents/Elsa.Agents.Persistence.EFCore/Elsa.Agents.Persistence.EFCore.csproj" + "id": "Elsa.Bpmn", + "project": "core/src/modules/Elsa.Bpmn/Elsa.Bpmn.csproj" }, { - "id": "Elsa.Agents.Persistence", - "project": "src/extensions/agents/Elsa.Agents.Persistence/Elsa.Agents.Persistence.csproj" + "id": "Elsa.Caching", + "project": "core/src/modules/Elsa.Caching/Elsa.Caching.csproj" }, { - "id": "Elsa.Agents", - "project": "src/extensions/agents/Elsa.Agents/Elsa.Agents.csproj" + "id": "Elsa.Common", + "project": "core/src/modules/Elsa.Common/Elsa.Common.csproj" }, { - "id": "Elsa.Studio.Agents", - "project": "src/extensions/agents/Elsa.Studio.Agents/Elsa.Studio.Agents.csproj" + "id": "Elsa.Connections.Credentials.Persistence.EFCore.PostgreSql", + "project": "core/src/modules/Elsa.Connections.Credentials.Persistence.EFCore.PostgreSql/Elsa.Connections.Credentials.Persistence.EFCore.PostgreSql.csproj" }, { - "id": "Elsa.Alterations.MassTransit", - "project": "src/extensions/alterations/Elsa.Alterations.MassTransit/Elsa.Alterations.MassTransit.csproj" + "id": "Elsa.Connections.Credentials.Persistence.EFCore", + "project": "core/src/modules/Elsa.Connections.Credentials.Persistence.EFCore/Elsa.Connections.Credentials.Persistence.EFCore.csproj" }, { - "id": "Elsa.Caching.Distributed.MassTransit", - "project": "src/extensions/caching/Elsa.Caching.Distributed.MassTransit/Elsa.Caching.Distributed.MassTransit.csproj" + "id": "Elsa.Connections.Credentials.Workflows", + "project": "core/src/modules/Elsa.Connections.Credentials.Workflows/Elsa.Connections.Credentials.Workflows.csproj" }, { - "id": "Elsa.Caching.Distributed.ProtoActor", - "project": "src/extensions/caching/Elsa.Caching.Distributed.ProtoActor/Elsa.Caching.Distributed.ProtoActor.csproj" + "id": "Elsa.Connections", + "project": "core/src/modules/Elsa.Connections/Elsa.Connections.csproj" }, { - "id": "Elsa.Caching.Distributed", - "project": "src/extensions/caching/Elsa.Caching.Distributed/Elsa.Caching.Distributed.csproj" + "id": "Elsa.Dashboard.Abstractions", + "project": "core/src/modules/Elsa.Dashboard.Abstractions/Elsa.Dashboard.Abstractions.csproj" }, { - "id": "Elsa.OrchardCore", - "project": "src/extensions/cms/Elsa.OrchardCore/Elsa.OrchardCore.csproj" + "id": "Elsa.Dashboard.Api", + "project": "core/src/modules/Elsa.Dashboard.Api/Elsa.Dashboard.Api.csproj" }, { - "id": "Elsa.Slack", - "project": "src/extensions/communication/Elsa.Slack/Elsa.Slack.csproj" + "id": "Elsa.Diagnostics.ConsoleLogs.Dashboard", + "project": "core/src/modules/Elsa.Diagnostics.ConsoleLogs.Dashboard/Elsa.Diagnostics.ConsoleLogs.Dashboard.csproj" }, { - "id": "Elsa.Connections.Api", - "project": "src/extensions/connections/Elsa.Connections.Api/Elsa.Connections.Api.csproj" + "id": "Elsa.Diagnostics.ConsoleLogs", + "project": "core/src/modules/Elsa.Diagnostics.ConsoleLogs/Elsa.Diagnostics.ConsoleLogs.csproj" }, { - "id": "Elsa.Connections.Core", - "project": "src/extensions/connections/Elsa.Connections.Core/Elsa.Connections.Core.csproj" + "id": "Elsa.Diagnostics.OpenTelemetry", + "project": "core/src/modules/Elsa.Diagnostics.OpenTelemetry/Elsa.Diagnostics.OpenTelemetry.csproj" }, { - "id": "Elsa.Connections.Models", - "project": "src/extensions/connections/Elsa.Connections.Models/Elsa.Connections.Models.csproj" + "id": "Elsa.Diagnostics.StructuredLogs.Dashboard", + "project": "core/src/modules/Elsa.Diagnostics.StructuredLogs.Dashboard/Elsa.Diagnostics.StructuredLogs.Dashboard.csproj" }, { - "id": "Elsa.Connections.Persistence.EFCore.Sqlite", - "project": "src/extensions/connections/Elsa.Connections.Persistence.EFCore.Sqlite/Elsa.Connections.Persistence.EFCore.Sqlite.csproj" + "id": "Elsa.Diagnostics.StructuredLogs.Persistence.Relational", + "project": "core/src/modules/Elsa.Diagnostics.StructuredLogs.Persistence.Relational/Elsa.Diagnostics.StructuredLogs.Persistence.Relational.csproj" }, { - "id": "Elsa.Connections.Persistence.EFCore", - "project": "src/extensions/connections/Elsa.Connections.Persistence.EFCore/Elsa.Connections.Persistence.EFCore.csproj" + "id": "Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite", + "project": "core/src/modules/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.csproj" }, { - "id": "Elsa.Connections.Persistence", - "project": "src/extensions/connections/Elsa.Connections.Persistence/Elsa.Connections.Persistence.csproj" + "id": "Elsa.Diagnostics.StructuredLogs", + "project": "core/src/modules/Elsa.Diagnostics.StructuredLogs/Elsa.Diagnostics.StructuredLogs.csproj" }, { - "id": "Elsa.Data.Csv", - "project": "src/extensions/data/Elsa.Data.Csv/Elsa.Data.Csv.csproj" + "id": "Elsa.Dsl.ElsaScript", + "project": "core/src/modules/Elsa.Dsl.ElsaScript/Elsa.Dsl.ElsaScript.csproj" }, { - "id": "Elsa.DevOps.GitHub", - "project": "src/extensions/devops/Elsa.DevOps.GitHub/Elsa.DevOps.GitHub.csproj" + "id": "Elsa.Expressions.CSharp", + "project": "core/src/modules/Elsa.Expressions.CSharp/Elsa.Expressions.CSharp.csproj" }, { - "id": "Elsa.Logging.Console", - "project": "src/extensions/diagnostics/Elsa.Logging.Console/Elsa.Logging.Console.csproj" + "id": "Elsa.Expressions.JavaScript.Libraries", + "project": "core/src/modules/Elsa.Expressions.JavaScript.Libraries/Elsa.Expressions.JavaScript.Libraries.csproj" }, { - "id": "Elsa.Logging.Core", - "project": "src/extensions/diagnostics/Elsa.Logging.Core/Elsa.Logging.Core.csproj" + "id": "Elsa.Expressions.JavaScript", + "project": "core/src/modules/Elsa.Expressions.JavaScript/Elsa.Expressions.JavaScript.csproj" }, { - "id": "Elsa.Logging.Serilog", - "project": "src/extensions/diagnostics/Elsa.Logging.Serilog/Elsa.Logging.Serilog.csproj" + "id": "Elsa.Expressions.Liquid", + "project": "core/src/modules/Elsa.Expressions.Liquid/Elsa.Expressions.Liquid.csproj" }, { - "id": "Elsa.Logging", - "project": "src/extensions/diagnostics/Elsa.Logging/Elsa.Logging.csproj" + "id": "Elsa.Expressions.Python", + "project": "core/src/modules/Elsa.Expressions.Python/Elsa.Expressions.Python.csproj" }, { - "id": "Elsa.OpenTelemetry", - "project": "src/extensions/diagnostics/Elsa.OpenTelemetry/Elsa.OpenTelemetry.csproj" + "id": "Elsa.Expressions", + "project": "core/src/modules/Elsa.Expressions/Elsa.Expressions.csproj" }, { - "id": "Elsa.DropIns.Core", - "project": "src/extensions/dropins/Elsa.DropIns.Core/Elsa.DropIns.Core.csproj" + "id": "Elsa.ExternalAuthentication.OpenIdConnect", + "project": "core/src/modules/Elsa.ExternalAuthentication.OpenIdConnect/Elsa.ExternalAuthentication.OpenIdConnect.csproj" }, { - "id": "Elsa.DropIns", - "project": "src/extensions/dropins/Elsa.DropIns/Elsa.DropIns.csproj" + "id": "Elsa.ExternalAuthentication.Persistence.EFCore.MySql", + "project": "core/src/modules/Elsa.ExternalAuthentication.Persistence.EFCore.MySql/Elsa.ExternalAuthentication.Persistence.EFCore.MySql.csproj" }, { - "id": "Elsa.Email", - "project": "src/extensions/email/Elsa.Email/Elsa.Email.csproj" + "id": "Elsa.ExternalAuthentication.Persistence.EFCore.Oracle", + "project": "core/src/modules/Elsa.ExternalAuthentication.Persistence.EFCore.Oracle/Elsa.ExternalAuthentication.Persistence.EFCore.Oracle.csproj" }, { - "id": "Elsa.Http.OpenApi", - "project": "src/extensions/http/Elsa.Http.OpenApi/Elsa.Http.OpenApi.csproj" + "id": "Elsa.ExternalAuthentication.Persistence.EFCore.PostgreSql", + "project": "core/src/modules/Elsa.ExternalAuthentication.Persistence.EFCore.PostgreSql/Elsa.ExternalAuthentication.Persistence.EFCore.PostgreSql.csproj" }, { - "id": "Elsa.IO.Compression", - "project": "src/extensions/io/Elsa.IO.Compression/Elsa.IO.Compression.csproj" + "id": "Elsa.ExternalAuthentication.Persistence.EFCore.SqlServer", + "project": "core/src/modules/Elsa.ExternalAuthentication.Persistence.EFCore.SqlServer/Elsa.ExternalAuthentication.Persistence.EFCore.SqlServer.csproj" }, { - "id": "Elsa.IO.Http", - "project": "src/extensions/io/Elsa.IO.Http/Elsa.IO.Http.csproj" + "id": "Elsa.ExternalAuthentication.Persistence.EFCore.Sqlite", + "project": "core/src/modules/Elsa.ExternalAuthentication.Persistence.EFCore.Sqlite/Elsa.ExternalAuthentication.Persistence.EFCore.Sqlite.csproj" }, { - "id": "Elsa.IO", - "project": "src/extensions/io/Elsa.IO/Elsa.IO.csproj" + "id": "Elsa.ExternalAuthentication.Persistence.EFCore", + "project": "core/src/modules/Elsa.ExternalAuthentication.Persistence.EFCore/Elsa.ExternalAuthentication.Persistence.EFCore.csproj" }, { - "id": "Elsa.Ldap", - "project": "src/extensions/ldap/Elsa.Ldap/Elsa.Ldap.csproj" + "id": "Elsa.ExternalAuthentication.Secrets", + "project": "core/src/modules/Elsa.ExternalAuthentication.Secrets/Elsa.ExternalAuthentication.Secrets.csproj" }, { - "id": "Elsa.Mqtt", - "project": "src/extensions/mqtt/Elsa.Mqtt/Elsa.Mqtt.csproj" + "id": "Elsa.ExternalAuthentication", + "project": "core/src/modules/Elsa.ExternalAuthentication/Elsa.ExternalAuthentication.csproj" }, { - "id": "Elsa.Persistence.Dapper.Migrations", - "project": "src/extensions/persistence/Elsa.Persistence.Dapper.Migrations/Elsa.Persistence.Dapper.Migrations.csproj" + "id": "Elsa.Hosting.Management", + "project": "core/src/modules/Elsa.Hosting.Management/Elsa.Hosting.Management.csproj" }, { - "id": "Elsa.Persistence.Dapper", - "project": "src/extensions/persistence/Elsa.Persistence.Dapper/Elsa.Persistence.Dapper.csproj" + "id": "Elsa.Http.Webhooks", + "project": "core/src/modules/Elsa.Http.Webhooks/Elsa.Http.Webhooks.csproj" }, { - "id": "Elsa.Persistence.Elasticsearch", - "project": "src/extensions/persistence/Elsa.Persistence.Elasticsearch/Elsa.Persistence.Elasticsearch.csproj" + "id": "Elsa.Http", + "project": "core/src/modules/Elsa.Http/Elsa.Http.csproj" }, { - "id": "Elsa.Persistence.MongoDb", - "project": "src/extensions/persistence/Elsa.Persistence.MongoDb/Elsa.Persistence.MongoDb.csproj" + "id": "Elsa.Identity", + "project": "core/src/modules/Elsa.Identity/Elsa.Identity.csproj" }, { - "id": "Elsa.Retention", - "project": "src/extensions/retention/Elsa.Retention/Elsa.Retention.csproj" + "id": "Elsa.KeyValues", + "project": "core/src/modules/Elsa.KeyValues/Elsa.KeyValues.csproj" }, { - "id": "Elsa.Workflows.Runtime.ProtoActor", - "project": "src/extensions/runtimes/Elsa.Workflows.Runtime.ProtoActor/Elsa.Workflows.Runtime.ProtoActor.csproj" + "id": "Elsa.Labels", + "project": "core/src/modules/Elsa.Labels/Elsa.Labels.csproj" }, { - "id": "Elsa.Scheduling.Hangfire", - "project": "src/extensions/scheduling/Elsa.Scheduling.Hangfire/Elsa.Scheduling.Hangfire.csproj" + "id": "Elsa.Persistence.EFCore.Common", + "project": "core/src/modules/Elsa.Persistence.EFCore.Common/Elsa.Persistence.EFCore.Common.csproj" }, { - "id": "Elsa.Scheduling.Quartz.EFCore.MySql", - "project": "src/extensions/scheduling/Elsa.Scheduling.Quartz.EFCore.MySql/Elsa.Scheduling.Quartz.EFCore.MySql.csproj" + "id": "Elsa.Persistence.EFCore.MySql", + "project": "core/src/modules/Elsa.Persistence.EFCore.MySql/Elsa.Persistence.EFCore.MySql.csproj" }, { - "id": "Elsa.Scheduling.Quartz.EFCore.PostgreSql", - "project": "src/extensions/scheduling/Elsa.Scheduling.Quartz.EFCore.PostgreSql/Elsa.Scheduling.Quartz.EFCore.PostgreSql.csproj" + "id": "Elsa.Persistence.EFCore.Oracle", + "project": "core/src/modules/Elsa.Persistence.EFCore.Oracle/Elsa.Persistence.EFCore.Oracle.csproj" }, { - "id": "Elsa.Scheduling.Quartz.EFCore.SqlServer", - "project": "src/extensions/scheduling/Elsa.Scheduling.Quartz.EFCore.SqlServer/Elsa.Scheduling.Quartz.EFCore.SqlServer.csproj" + "id": "Elsa.Persistence.EFCore.PostgreSql", + "project": "core/src/modules/Elsa.Persistence.EFCore.PostgreSql/Elsa.Persistence.EFCore.PostgreSql.csproj" }, { - "id": "Elsa.Scheduling.Quartz.EFCore.Sqlite", - "project": "src/extensions/scheduling/Elsa.Scheduling.Quartz.EFCore.Sqlite/Elsa.Scheduling.Quartz.EFCore.Sqlite.csproj" + "id": "Elsa.Persistence.EFCore.SqlServer", + "project": "core/src/modules/Elsa.Persistence.EFCore.SqlServer/Elsa.Persistence.EFCore.SqlServer.csproj" }, { - "id": "Elsa.Scheduling.Quartz", - "project": "src/extensions/scheduling/Elsa.Scheduling.Quartz/Elsa.Scheduling.Quartz.csproj" + "id": "Elsa.Persistence.EFCore.Sqlite", + "project": "core/src/modules/Elsa.Persistence.EFCore.Sqlite/Elsa.Persistence.EFCore.Sqlite.csproj" }, { - "id": "Elsa.ServiceBus.AzureServiceBus", - "project": "src/extensions/servicebus/Elsa.ServiceBus.AzureServiceBus/Elsa.ServiceBus.AzureServiceBus.csproj" + "id": "Elsa.Persistence.EFCore", + "project": "core/src/modules/Elsa.Persistence.EFCore/Elsa.Persistence.EFCore.csproj" }, { - "id": "Elsa.ServiceBus.Kafka", - "project": "src/extensions/servicebus/Elsa.ServiceBus.Kafka/Elsa.ServiceBus.Kafka.csproj" + "id": "Elsa.Persistence.VNext.Extensions", + "project": "core/src/modules/Elsa.Persistence.VNext.Extensions/Elsa.Persistence.VNext.Extensions.csproj" }, { - "id": "Elsa.ServiceBus.MassTransit.AzureServiceBus", - "project": "src/extensions/servicebus/Elsa.ServiceBus.MassTransit.AzureServiceBus/Elsa.ServiceBus.MassTransit.AzureServiceBus.csproj" + "id": "Elsa.Persistence.VNext.MongoDb", + "project": "core/src/modules/Elsa.Persistence.VNext.MongoDb/Elsa.Persistence.VNext.MongoDb.csproj" }, { - "id": "Elsa.ServiceBus.MassTransit.RabbitMq", - "project": "src/extensions/servicebus/Elsa.ServiceBus.MassTransit.RabbitMq/Elsa.ServiceBus.MassTransit.RabbitMq.csproj" + "id": "Elsa.Persistence.VNext.PostgreSql", + "project": "core/src/modules/Elsa.Persistence.VNext.PostgreSql/Elsa.Persistence.VNext.PostgreSql.csproj" }, { - "id": "Elsa.ServiceBus.MassTransit", - "project": "src/extensions/servicebus/Elsa.ServiceBus.MassTransit/Elsa.ServiceBus.MassTransit.csproj" + "id": "Elsa.Persistence.VNext.Relational", + "project": "core/src/modules/Elsa.Persistence.VNext.Relational/Elsa.Persistence.VNext.Relational.csproj" }, { - "id": "Elsa.Sql.MySql", - "project": "src/extensions/sql/Elsa.Sql.MySql/Elsa.Sql.MySql.csproj" + "id": "Elsa.Persistence.VNext.Runtime", + "project": "core/src/modules/Elsa.Persistence.VNext.Runtime/Elsa.Persistence.VNext.Runtime.csproj" }, { - "id": "Elsa.Sql.PostgreSql", - "project": "src/extensions/sql/Elsa.Sql.PostgreSql/Elsa.Sql.PostgreSql.csproj" + "id": "Elsa.Persistence.VNext.SqlServer", + "project": "core/src/modules/Elsa.Persistence.VNext.SqlServer/Elsa.Persistence.VNext.SqlServer.csproj" }, { - "id": "Elsa.Sql.SqlServer", - "project": "src/extensions/sql/Elsa.Sql.SqlServer/Elsa.Sql.SqlServer.csproj" + "id": "Elsa.Persistence.VNext.Sqlite", + "project": "core/src/modules/Elsa.Persistence.VNext.Sqlite/Elsa.Persistence.VNext.Sqlite.csproj" }, { - "id": "Elsa.Sql.Sqlite", - "project": "src/extensions/sql/Elsa.Sql.Sqlite/Elsa.Sql.Sqlite.csproj" + "id": "Elsa.Persistence.VNext", + "project": "core/src/modules/Elsa.Persistence.VNext/Elsa.Persistence.VNext.csproj" }, { - "id": "Elsa.Sql", - "project": "src/extensions/sql/Elsa.Sql/Elsa.Sql.csproj" + "id": "Elsa.Platform.Integration", + "project": "core/src/modules/Elsa.Platform.Integration/Elsa.Platform.Integration.csproj" }, { - "id": "Elsa.Storage.AzureStorage", - "project": "src/extensions/storage/Elsa.Storage.AzureStorage/Elsa.Storage.AzureStorage.csproj" + "id": "Elsa.Resilience.Core", + "project": "core/src/modules/Elsa.Resilience.Core/Elsa.Resilience.Core.csproj" }, { - "id": "Elsa.Storage.Files", - "project": "src/extensions/storage/Elsa.Storage.Files/Elsa.Storage.Files.csproj" + "id": "Elsa.Resilience", + "project": "core/src/modules/Elsa.Resilience/Elsa.Resilience.csproj" }, { - "id": "Elsa.Telnyx", - "project": "src/extensions/telecom/Elsa.Telnyx/Elsa.Telnyx.csproj" + "id": "Elsa.SasTokens", + "project": "core/src/modules/Elsa.SasTokens/Elsa.SasTokens.csproj" }, { - "id": "Elsa.Studio.WorkflowContexts", - "project": "src/extensions/workflows/Elsa.Studio.WorkflowContexts/Elsa.Studio.WorkflowContexts.csproj" + "id": "Elsa.Scheduling", + "project": "core/src/modules/Elsa.Scheduling/Elsa.Scheduling.csproj" }, { - "id": "Elsa.WorkflowContexts", - "project": "src/extensions/workflows/Elsa.WorkflowContexts/Elsa.WorkflowContexts.csproj" + "id": "Elsa.Secrets.JavaScript", + "project": "core/src/modules/Elsa.Secrets.JavaScript/Elsa.Secrets.JavaScript.csproj" }, { - "id": "Elsa.AI.Abstractions", - "project": "src/modules/Elsa.AI.Abstractions/Elsa.AI.Abstractions.csproj" + "id": "Elsa.Secrets.Persistence.EFCore.MySql", + "project": "core/src/modules/Elsa.Secrets.Persistence.EFCore.MySql/Elsa.Secrets.Persistence.EFCore.MySql.csproj" }, { - "id": "Elsa.AI.Copilot", - "project": "src/modules/Elsa.AI.Copilot/Elsa.AI.Copilot.csproj" + "id": "Elsa.Secrets.Persistence.EFCore.Oracle", + "project": "core/src/modules/Elsa.Secrets.Persistence.EFCore.Oracle/Elsa.Secrets.Persistence.EFCore.Oracle.csproj" }, { - "id": "Elsa.AI.Host", - "project": "src/modules/Elsa.AI.Host/Elsa.AI.Host.csproj" + "id": "Elsa.Secrets.Persistence.EFCore.PostgreSql", + "project": "core/src/modules/Elsa.Secrets.Persistence.EFCore.PostgreSql/Elsa.Secrets.Persistence.EFCore.PostgreSql.csproj" }, { - "id": "Elsa.AI.Persistence.EFCore.MySql", - "project": "src/modules/Elsa.AI.Persistence.EFCore.MySql/Elsa.AI.Persistence.EFCore.MySql.csproj" + "id": "Elsa.Secrets.Persistence.EFCore.SqlServer", + "project": "core/src/modules/Elsa.Secrets.Persistence.EFCore.SqlServer/Elsa.Secrets.Persistence.EFCore.SqlServer.csproj" }, { - "id": "Elsa.AI.Persistence.EFCore.Oracle", - "project": "src/modules/Elsa.AI.Persistence.EFCore.Oracle/Elsa.AI.Persistence.EFCore.Oracle.csproj" + "id": "Elsa.Secrets.Persistence.EFCore.Sqlite", + "project": "core/src/modules/Elsa.Secrets.Persistence.EFCore.Sqlite/Elsa.Secrets.Persistence.EFCore.Sqlite.csproj" }, { - "id": "Elsa.AI.Persistence.EFCore.PostgreSql", - "project": "src/modules/Elsa.AI.Persistence.EFCore.PostgreSql/Elsa.AI.Persistence.EFCore.PostgreSql.csproj" + "id": "Elsa.Secrets.Persistence.EFCore", + "project": "core/src/modules/Elsa.Secrets.Persistence.EFCore/Elsa.Secrets.Persistence.EFCore.csproj" }, { - "id": "Elsa.AI.Persistence.EFCore.SqlServer", - "project": "src/modules/Elsa.AI.Persistence.EFCore.SqlServer/Elsa.AI.Persistence.EFCore.SqlServer.csproj" + "id": "Elsa.Secrets.Persistence.VNext", + "project": "core/src/modules/Elsa.Secrets.Persistence.VNext/Elsa.Secrets.Persistence.VNext.csproj" }, { - "id": "Elsa.AI.Persistence.EFCore.Sqlite", - "project": "src/modules/Elsa.AI.Persistence.EFCore.Sqlite/Elsa.AI.Persistence.EFCore.Sqlite.csproj" + "id": "Elsa.Secrets", + "project": "core/src/modules/Elsa.Secrets/Elsa.Secrets.csproj" }, { - "id": "Elsa.AI.Persistence.EFCore", - "project": "src/modules/Elsa.AI.Persistence.EFCore/Elsa.AI.Persistence.EFCore.csproj" + "id": "Elsa.Shells.Api", + "project": "core/src/modules/Elsa.Shells.Api/Elsa.Shells.Api.csproj" }, { - "id": "Elsa.Alterations.Core", - "project": "src/modules/Elsa.Alterations.Core/Elsa.Alterations.Core.csproj" + "id": "Elsa.Tenants.AspNetCore", + "project": "core/src/modules/Elsa.Tenants.AspNetCore/Elsa.Tenants.AspNetCore.csproj" }, { - "id": "Elsa.Alterations", - "project": "src/modules/Elsa.Alterations/Elsa.Alterations.csproj" + "id": "Elsa.Tenants", + "project": "core/src/modules/Elsa.Tenants/Elsa.Tenants.csproj" }, { - "id": "Elsa.Bpmn.Interchange", - "project": "src/modules/Elsa.Bpmn.Interchange/Elsa.Bpmn.Interchange.csproj" + "id": "Elsa.UserTasks.Persistence.EFCore.MySql", + "project": "core/src/modules/Elsa.UserTasks.Persistence.EFCore.MySql/Elsa.UserTasks.Persistence.EFCore.MySql.csproj" }, { - "id": "Elsa.Bpmn", - "project": "src/modules/Elsa.Bpmn/Elsa.Bpmn.csproj" + "id": "Elsa.UserTasks.Persistence.EFCore.Oracle", + "project": "core/src/modules/Elsa.UserTasks.Persistence.EFCore.Oracle/Elsa.UserTasks.Persistence.EFCore.Oracle.csproj" }, { - "id": "Elsa.Caching", - "project": "src/modules/Elsa.Caching/Elsa.Caching.csproj" + "id": "Elsa.UserTasks.Persistence.EFCore.PostgreSql", + "project": "core/src/modules/Elsa.UserTasks.Persistence.EFCore.PostgreSql/Elsa.UserTasks.Persistence.EFCore.PostgreSql.csproj" }, { - "id": "Elsa.Common", - "project": "src/modules/Elsa.Common/Elsa.Common.csproj" + "id": "Elsa.UserTasks.Persistence.EFCore.SqlServer", + "project": "core/src/modules/Elsa.UserTasks.Persistence.EFCore.SqlServer/Elsa.UserTasks.Persistence.EFCore.SqlServer.csproj" }, { - "id": "Elsa.Dashboard.Abstractions", - "project": "src/modules/Elsa.Dashboard.Abstractions/Elsa.Dashboard.Abstractions.csproj" + "id": "Elsa.UserTasks.Persistence.EFCore.Sqlite", + "project": "core/src/modules/Elsa.UserTasks.Persistence.EFCore.Sqlite/Elsa.UserTasks.Persistence.EFCore.Sqlite.csproj" }, { - "id": "Elsa.Dashboard.Api", - "project": "src/modules/Elsa.Dashboard.Api/Elsa.Dashboard.Api.csproj" + "id": "Elsa.UserTasks.Persistence.EFCore", + "project": "core/src/modules/Elsa.UserTasks.Persistence.EFCore/Elsa.UserTasks.Persistence.EFCore.csproj" }, { - "id": "Elsa.Diagnostics.ConsoleLogs.Dashboard", - "project": "src/modules/Elsa.Diagnostics.ConsoleLogs.Dashboard/Elsa.Diagnostics.ConsoleLogs.Dashboard.csproj" + "id": "Elsa.UserTasks.Persistence.VNext", + "project": "core/src/modules/Elsa.UserTasks.Persistence.VNext/Elsa.UserTasks.Persistence.VNext.csproj" }, { - "id": "Elsa.Diagnostics.ConsoleLogs", - "project": "src/modules/Elsa.Diagnostics.ConsoleLogs/Elsa.Diagnostics.ConsoleLogs.csproj" + "id": "Elsa.UserTasks", + "project": "core/src/modules/Elsa.UserTasks/Elsa.UserTasks.csproj" }, { - "id": "Elsa.Diagnostics.OpenTelemetry", - "project": "src/modules/Elsa.Diagnostics.OpenTelemetry/Elsa.Diagnostics.OpenTelemetry.csproj" + "id": "Elsa.WorkflowProviders.BlobStorage.ElsaScript", + "project": "core/src/modules/Elsa.WorkflowProviders.BlobStorage.ElsaScript/Elsa.WorkflowProviders.BlobStorage.ElsaScript.csproj" }, { - "id": "Elsa.Diagnostics.StructuredLogs.Dashboard", - "project": "src/modules/Elsa.Diagnostics.StructuredLogs.Dashboard/Elsa.Diagnostics.StructuredLogs.Dashboard.csproj" + "id": "Elsa.WorkflowProviders.BlobStorage", + "project": "core/src/modules/Elsa.WorkflowProviders.BlobStorage/Elsa.WorkflowProviders.BlobStorage.csproj" }, { - "id": "Elsa.Diagnostics.StructuredLogs.Persistence.Relational", - "project": "src/modules/Elsa.Diagnostics.StructuredLogs.Persistence.Relational/Elsa.Diagnostics.StructuredLogs.Persistence.Relational.csproj" + "id": "Elsa.Workflows.Admission.Persistence.EFCore.PostgreSql", + "project": "core/src/modules/Elsa.Workflows.Admission.Persistence.EFCore.PostgreSql/Elsa.Workflows.Admission.Persistence.EFCore.PostgreSql.csproj" }, { - "id": "Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite", - "project": "src/modules/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite/Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite.csproj" + "id": "Elsa.Workflows.Admission.Persistence.EFCore", + "project": "core/src/modules/Elsa.Workflows.Admission.Persistence.EFCore/Elsa.Workflows.Admission.Persistence.EFCore.csproj" }, { - "id": "Elsa.Diagnostics.StructuredLogs", - "project": "src/modules/Elsa.Diagnostics.StructuredLogs/Elsa.Diagnostics.StructuredLogs.csproj" + "id": "Elsa.Workflows.Admission", + "project": "core/src/modules/Elsa.Workflows.Admission/Elsa.Workflows.Admission.csproj" }, { - "id": "Elsa.Dsl.ElsaScript", - "project": "src/modules/Elsa.Dsl.ElsaScript/Elsa.Dsl.ElsaScript.csproj" + "id": "Elsa.Workflows.Api", + "project": "core/src/modules/Elsa.Workflows.Api/Elsa.Workflows.Api.csproj" }, { - "id": "Elsa.Expressions.CSharp", - "project": "src/modules/Elsa.Expressions.CSharp/Elsa.Expressions.CSharp.csproj" + "id": "Elsa.Workflows.Core", + "project": "core/src/modules/Elsa.Workflows.Core/Elsa.Workflows.Core.csproj" }, { - "id": "Elsa.Expressions.JavaScript.Libraries", - "project": "src/modules/Elsa.Expressions.JavaScript.Libraries/Elsa.Expressions.JavaScript.Libraries.csproj" + "id": "Elsa.Workflows.Management", + "project": "core/src/modules/Elsa.Workflows.Management/Elsa.Workflows.Management.csproj" }, { - "id": "Elsa.Expressions.JavaScript", - "project": "src/modules/Elsa.Expressions.JavaScript/Elsa.Expressions.JavaScript.csproj" + "id": "Elsa.Workflows.Runtime.Dashboard", + "project": "core/src/modules/Elsa.Workflows.Runtime.Dashboard/Elsa.Workflows.Runtime.Dashboard.csproj" }, { - "id": "Elsa.Expressions.Liquid", - "project": "src/modules/Elsa.Expressions.Liquid/Elsa.Expressions.Liquid.csproj" + "id": "Elsa.Workflows.Runtime.Distributed", + "project": "core/src/modules/Elsa.Workflows.Runtime.Distributed/Elsa.Workflows.Runtime.Distributed.csproj" }, { - "id": "Elsa.Expressions.Python", - "project": "src/modules/Elsa.Expressions.Python/Elsa.Expressions.Python.csproj" + "id": "Elsa.Workflows.Runtime", + "project": "core/src/modules/Elsa.Workflows.Runtime/Elsa.Workflows.Runtime.csproj" }, { - "id": "Elsa.Expressions", - "project": "src/modules/Elsa.Expressions/Elsa.Expressions.csproj" + "id": "Elsa", + "project": "core/src/modules/Elsa/Elsa.csproj" }, { - "id": "Elsa.ExternalAuthentication.OpenIdConnect", - "project": "src/modules/Elsa.ExternalAuthentication.OpenIdConnect/Elsa.ExternalAuthentication.OpenIdConnect.csproj" + "id": "Elsa.Actors.ProtoActor.PubSub.Redis", + "project": "extensions/src/actors/Elsa.Actors.ProtoActor.PubSub.Redis/Elsa.Actors.ProtoActor.PubSub.Redis.csproj" }, { - "id": "Elsa.ExternalAuthentication.Persistence.EFCore.MySql", - "project": "src/modules/Elsa.ExternalAuthentication.Persistence.EFCore.MySql/Elsa.ExternalAuthentication.Persistence.EFCore.MySql.csproj" + "id": "Elsa.Actors.ProtoActor", + "project": "extensions/src/actors/Elsa.Actors.ProtoActor/Elsa.Actors.ProtoActor.csproj" }, { - "id": "Elsa.ExternalAuthentication.Persistence.EFCore.Oracle", - "project": "src/modules/Elsa.ExternalAuthentication.Persistence.EFCore.Oracle/Elsa.ExternalAuthentication.Persistence.EFCore.Oracle.csproj" + "id": "Elsa.Agents.Activities", + "project": "extensions/src/agents/Elsa.Agents.Activities/Elsa.Agents.Activities.csproj" }, { - "id": "Elsa.ExternalAuthentication.Persistence.EFCore.PostgreSql", - "project": "src/modules/Elsa.ExternalAuthentication.Persistence.EFCore.PostgreSql/Elsa.ExternalAuthentication.Persistence.EFCore.PostgreSql.csproj" + "id": "Elsa.Agents.Api", + "project": "extensions/src/agents/Elsa.Agents.Api/Elsa.Agents.Api.csproj" }, { - "id": "Elsa.ExternalAuthentication.Persistence.EFCore.SqlServer", - "project": "src/modules/Elsa.ExternalAuthentication.Persistence.EFCore.SqlServer/Elsa.ExternalAuthentication.Persistence.EFCore.SqlServer.csproj" + "id": "Elsa.Agents.AzureOpenAI", + "project": "extensions/src/agents/Elsa.Agents.AzureOpenAI/Elsa.Agents.AzureOpenAI.csproj" }, { - "id": "Elsa.ExternalAuthentication.Persistence.EFCore.Sqlite", - "project": "src/modules/Elsa.ExternalAuthentication.Persistence.EFCore.Sqlite/Elsa.ExternalAuthentication.Persistence.EFCore.Sqlite.csproj" + "id": "Elsa.Agents.Core", + "project": "extensions/src/agents/Elsa.Agents.Core/Elsa.Agents.Core.csproj" }, { - "id": "Elsa.ExternalAuthentication.Persistence.EFCore", - "project": "src/modules/Elsa.ExternalAuthentication.Persistence.EFCore/Elsa.ExternalAuthentication.Persistence.EFCore.csproj" + "id": "Elsa.Agents.Models", + "project": "extensions/src/agents/Elsa.Agents.Models/Elsa.Agents.Models.csproj" }, { - "id": "Elsa.ExternalAuthentication.Secrets", - "project": "src/modules/Elsa.ExternalAuthentication.Secrets/Elsa.ExternalAuthentication.Secrets.csproj" + "id": "Elsa.Agents.OpenAI", + "project": "extensions/src/agents/Elsa.Agents.OpenAI/Elsa.Agents.OpenAI.csproj" }, { - "id": "Elsa.ExternalAuthentication", - "project": "src/modules/Elsa.ExternalAuthentication/Elsa.ExternalAuthentication.csproj" + "id": "Elsa.Agents.Persistence.EFCore.MySql", + "project": "extensions/src/agents/Elsa.Agents.Persistence.EFCore.MySql/Elsa.Agents.Persistence.EFCore.MySql.csproj" }, { - "id": "Elsa.Hosting.Management", - "project": "src/modules/Elsa.Hosting.Management/Elsa.Hosting.Management.csproj" + "id": "Elsa.Agents.Persistence.EFCore.PostgreSql", + "project": "extensions/src/agents/Elsa.Agents.Persistence.EFCore.PostgreSql/Elsa.Agents.Persistence.EFCore.PostgreSql.csproj" }, { - "id": "Elsa.Http.Webhooks", - "project": "src/modules/Elsa.Http.Webhooks/Elsa.Http.Webhooks.csproj" + "id": "Elsa.Agents.Persistence.EFCore.SqlServer", + "project": "extensions/src/agents/Elsa.Agents.Persistence.EFCore.SqlServer/Elsa.Agents.Persistence.EFCore.SqlServer.csproj" }, { - "id": "Elsa.Http", - "project": "src/modules/Elsa.Http/Elsa.Http.csproj" + "id": "Elsa.Agents.Persistence.EFCore.Sqlite", + "project": "extensions/src/agents/Elsa.Agents.Persistence.EFCore.Sqlite/Elsa.Agents.Persistence.EFCore.Sqlite.csproj" }, { - "id": "Elsa.Identity", - "project": "src/modules/Elsa.Identity/Elsa.Identity.csproj" + "id": "Elsa.Agents.Persistence.EFCore", + "project": "extensions/src/agents/Elsa.Agents.Persistence.EFCore/Elsa.Agents.Persistence.EFCore.csproj" }, { - "id": "Elsa.KeyValues", - "project": "src/modules/Elsa.KeyValues/Elsa.KeyValues.csproj" + "id": "Elsa.Agents.Persistence", + "project": "extensions/src/agents/Elsa.Agents.Persistence/Elsa.Agents.Persistence.csproj" }, { - "id": "Elsa.Labels", - "project": "src/modules/Elsa.Labels/Elsa.Labels.csproj" + "id": "Elsa.Agents", + "project": "extensions/src/agents/Elsa.Agents/Elsa.Agents.csproj" }, { - "id": "Elsa.Persistence.EFCore.Common", - "project": "src/modules/Elsa.Persistence.EFCore.Common/Elsa.Persistence.EFCore.Common.csproj" + "id": "Elsa.Studio.Agents", + "project": "extensions/src/agents/Elsa.Studio.Agents/Elsa.Studio.Agents.csproj" }, { - "id": "Elsa.Persistence.EFCore.MySql", - "project": "src/modules/Elsa.Persistence.EFCore.MySql/Elsa.Persistence.EFCore.MySql.csproj" + "id": "Elsa.Alterations.MassTransit", + "project": "extensions/src/alterations/Elsa.Alterations.MassTransit/Elsa.Alterations.MassTransit.csproj" }, { - "id": "Elsa.Persistence.EFCore.Oracle", - "project": "src/modules/Elsa.Persistence.EFCore.Oracle/Elsa.Persistence.EFCore.Oracle.csproj" + "id": "Elsa.Caching.Distributed.MassTransit", + "project": "extensions/src/caching/Elsa.Caching.Distributed.MassTransit/Elsa.Caching.Distributed.MassTransit.csproj" }, { - "id": "Elsa.Persistence.EFCore.PostgreSql", - "project": "src/modules/Elsa.Persistence.EFCore.PostgreSql/Elsa.Persistence.EFCore.PostgreSql.csproj" + "id": "Elsa.Caching.Distributed.ProtoActor", + "project": "extensions/src/caching/Elsa.Caching.Distributed.ProtoActor/Elsa.Caching.Distributed.ProtoActor.csproj" }, { - "id": "Elsa.Persistence.EFCore.SqlServer", - "project": "src/modules/Elsa.Persistence.EFCore.SqlServer/Elsa.Persistence.EFCore.SqlServer.csproj" + "id": "Elsa.Caching.Distributed", + "project": "extensions/src/caching/Elsa.Caching.Distributed/Elsa.Caching.Distributed.csproj" }, { - "id": "Elsa.Persistence.EFCore.Sqlite", - "project": "src/modules/Elsa.Persistence.EFCore.Sqlite/Elsa.Persistence.EFCore.Sqlite.csproj" + "id": "Elsa.OrchardCore", + "project": "extensions/src/cms/Elsa.OrchardCore/Elsa.OrchardCore.csproj" }, { - "id": "Elsa.Persistence.EFCore", - "project": "src/modules/Elsa.Persistence.EFCore/Elsa.Persistence.EFCore.csproj" + "id": "Elsa.Slack", + "project": "extensions/src/communication/Elsa.Slack/Elsa.Slack.csproj" }, { - "id": "Elsa.Persistence.VNext.Extensions", - "project": "src/modules/Elsa.Persistence.VNext.Extensions/Elsa.Persistence.VNext.Extensions.csproj" + "id": "Elsa.Connections.Api", + "project": "extensions/src/connections/Elsa.Connections.Api/Elsa.Connections.Api.csproj" }, { - "id": "Elsa.Persistence.VNext.MongoDb", - "project": "src/modules/Elsa.Persistence.VNext.MongoDb/Elsa.Persistence.VNext.MongoDb.csproj" + "id": "Elsa.Connections.Core", + "project": "extensions/src/connections/Elsa.Connections.Core/Elsa.Connections.Core.csproj" }, { - "id": "Elsa.Persistence.VNext.PostgreSql", - "project": "src/modules/Elsa.Persistence.VNext.PostgreSql/Elsa.Persistence.VNext.PostgreSql.csproj" + "id": "Elsa.Connections.Models", + "project": "extensions/src/connections/Elsa.Connections.Models/Elsa.Connections.Models.csproj" }, { - "id": "Elsa.Persistence.VNext.Relational", - "project": "src/modules/Elsa.Persistence.VNext.Relational/Elsa.Persistence.VNext.Relational.csproj" + "id": "Elsa.Connections.Persistence.EFCore.Sqlite", + "project": "extensions/src/connections/Elsa.Connections.Persistence.EFCore.Sqlite/Elsa.Connections.Persistence.EFCore.Sqlite.csproj" }, { - "id": "Elsa.Persistence.VNext.Runtime", - "project": "src/modules/Elsa.Persistence.VNext.Runtime/Elsa.Persistence.VNext.Runtime.csproj" + "id": "Elsa.Connections.Persistence.EFCore", + "project": "extensions/src/connections/Elsa.Connections.Persistence.EFCore/Elsa.Connections.Persistence.EFCore.csproj" }, { - "id": "Elsa.Persistence.VNext.SqlServer", - "project": "src/modules/Elsa.Persistence.VNext.SqlServer/Elsa.Persistence.VNext.SqlServer.csproj" + "id": "Elsa.Connections.Persistence", + "project": "extensions/src/connections/Elsa.Connections.Persistence/Elsa.Connections.Persistence.csproj" }, { - "id": "Elsa.Persistence.VNext.Sqlite", - "project": "src/modules/Elsa.Persistence.VNext.Sqlite/Elsa.Persistence.VNext.Sqlite.csproj" + "id": "Elsa.Data.Csv", + "project": "extensions/src/data/Elsa.Data.Csv/Elsa.Data.Csv.csproj" }, { - "id": "Elsa.Persistence.VNext", - "project": "src/modules/Elsa.Persistence.VNext/Elsa.Persistence.VNext.csproj" + "id": "Elsa.DevOps.GitHub", + "project": "extensions/src/devops/Elsa.DevOps.GitHub/Elsa.DevOps.GitHub.csproj" }, { - "id": "Elsa.Platform.Integration", - "project": "src/modules/Elsa.Platform.Integration/Elsa.Platform.Integration.csproj" + "id": "Elsa.Logging.Console", + "project": "extensions/src/diagnostics/Elsa.Logging.Console/Elsa.Logging.Console.csproj" }, { - "id": "Elsa.Resilience.Core", - "project": "src/modules/Elsa.Resilience.Core/Elsa.Resilience.Core.csproj" + "id": "Elsa.Logging.Core", + "project": "extensions/src/diagnostics/Elsa.Logging.Core/Elsa.Logging.Core.csproj" }, { - "id": "Elsa.Resilience", - "project": "src/modules/Elsa.Resilience/Elsa.Resilience.csproj" + "id": "Elsa.Logging.Serilog", + "project": "extensions/src/diagnostics/Elsa.Logging.Serilog/Elsa.Logging.Serilog.csproj" }, { - "id": "Elsa.SasTokens", - "project": "src/modules/Elsa.SasTokens/Elsa.SasTokens.csproj" + "id": "Elsa.Logging", + "project": "extensions/src/diagnostics/Elsa.Logging/Elsa.Logging.csproj" }, { - "id": "Elsa.Scheduling", - "project": "src/modules/Elsa.Scheduling/Elsa.Scheduling.csproj" + "id": "Elsa.OpenTelemetry", + "project": "extensions/src/diagnostics/Elsa.OpenTelemetry/Elsa.OpenTelemetry.csproj" }, { - "id": "Elsa.Secrets.JavaScript", - "project": "src/modules/Elsa.Secrets.JavaScript/Elsa.Secrets.JavaScript.csproj" + "id": "Elsa.DropIns.Core", + "project": "extensions/src/dropins/Elsa.DropIns.Core/Elsa.DropIns.Core.csproj" }, { - "id": "Elsa.Secrets.Persistence.EFCore.MySql", - "project": "src/modules/Elsa.Secrets.Persistence.EFCore.MySql/Elsa.Secrets.Persistence.EFCore.MySql.csproj" + "id": "Elsa.DropIns", + "project": "extensions/src/dropins/Elsa.DropIns/Elsa.DropIns.csproj" }, { - "id": "Elsa.Secrets.Persistence.EFCore.Oracle", - "project": "src/modules/Elsa.Secrets.Persistence.EFCore.Oracle/Elsa.Secrets.Persistence.EFCore.Oracle.csproj" + "id": "Elsa.Email", + "project": "extensions/src/email/Elsa.Email/Elsa.Email.csproj" }, { - "id": "Elsa.Secrets.Persistence.EFCore.PostgreSql", - "project": "src/modules/Elsa.Secrets.Persistence.EFCore.PostgreSql/Elsa.Secrets.Persistence.EFCore.PostgreSql.csproj" + "id": "Elsa.Http.OpenApi", + "project": "extensions/src/http/Elsa.Http.OpenApi/Elsa.Http.OpenApi.csproj" }, { - "id": "Elsa.Secrets.Persistence.EFCore.SqlServer", - "project": "src/modules/Elsa.Secrets.Persistence.EFCore.SqlServer/Elsa.Secrets.Persistence.EFCore.SqlServer.csproj" + "id": "Elsa.IO.Compression", + "project": "extensions/src/io/Elsa.IO.Compression/Elsa.IO.Compression.csproj" }, { - "id": "Elsa.Secrets.Persistence.EFCore.Sqlite", - "project": "src/modules/Elsa.Secrets.Persistence.EFCore.Sqlite/Elsa.Secrets.Persistence.EFCore.Sqlite.csproj" + "id": "Elsa.IO.Http", + "project": "extensions/src/io/Elsa.IO.Http/Elsa.IO.Http.csproj" }, { - "id": "Elsa.Secrets.Persistence.EFCore", - "project": "src/modules/Elsa.Secrets.Persistence.EFCore/Elsa.Secrets.Persistence.EFCore.csproj" + "id": "Elsa.IO", + "project": "extensions/src/io/Elsa.IO/Elsa.IO.csproj" }, { - "id": "Elsa.Secrets.Persistence.VNext", - "project": "src/modules/Elsa.Secrets.Persistence.VNext/Elsa.Secrets.Persistence.VNext.csproj" + "id": "Elsa.Ldap", + "project": "extensions/src/ldap/Elsa.Ldap/Elsa.Ldap.csproj" }, { - "id": "Elsa.Secrets", - "project": "src/modules/Elsa.Secrets/Elsa.Secrets.csproj" + "id": "Elsa.Mqtt", + "project": "extensions/src/mqtt/Elsa.Mqtt/Elsa.Mqtt.csproj" }, { - "id": "Elsa.Shells.Api", - "project": "src/modules/Elsa.Shells.Api/Elsa.Shells.Api.csproj" + "id": "Elsa.Persistence.Dapper.Migrations", + "project": "extensions/src/persistence/Elsa.Persistence.Dapper.Migrations/Elsa.Persistence.Dapper.Migrations.csproj" }, { - "id": "Elsa.Tenants.AspNetCore", - "project": "src/modules/Elsa.Tenants.AspNetCore/Elsa.Tenants.AspNetCore.csproj" + "id": "Elsa.Persistence.Dapper", + "project": "extensions/src/persistence/Elsa.Persistence.Dapper/Elsa.Persistence.Dapper.csproj" }, { - "id": "Elsa.Tenants", - "project": "src/modules/Elsa.Tenants/Elsa.Tenants.csproj" + "id": "Elsa.Persistence.Elasticsearch", + "project": "extensions/src/persistence/Elsa.Persistence.Elasticsearch/Elsa.Persistence.Elasticsearch.csproj" }, { - "id": "Elsa.UserTasks.Persistence.EFCore.MySql", - "project": "src/modules/Elsa.UserTasks.Persistence.EFCore.MySql/Elsa.UserTasks.Persistence.EFCore.MySql.csproj" + "id": "Elsa.Persistence.MongoDb", + "project": "extensions/src/persistence/Elsa.Persistence.MongoDb/Elsa.Persistence.MongoDb.csproj" }, { - "id": "Elsa.UserTasks.Persistence.EFCore.Oracle", - "project": "src/modules/Elsa.UserTasks.Persistence.EFCore.Oracle/Elsa.UserTasks.Persistence.EFCore.Oracle.csproj" + "id": "Elsa.Retention", + "project": "extensions/src/retention/Elsa.Retention/Elsa.Retention.csproj" }, { - "id": "Elsa.UserTasks.Persistence.EFCore.PostgreSql", - "project": "src/modules/Elsa.UserTasks.Persistence.EFCore.PostgreSql/Elsa.UserTasks.Persistence.EFCore.PostgreSql.csproj" + "id": "Elsa.Workflows.Runtime.ProtoActor", + "project": "extensions/src/runtimes/Elsa.Workflows.Runtime.ProtoActor/Elsa.Workflows.Runtime.ProtoActor.csproj" }, { - "id": "Elsa.UserTasks.Persistence.EFCore.SqlServer", - "project": "src/modules/Elsa.UserTasks.Persistence.EFCore.SqlServer/Elsa.UserTasks.Persistence.EFCore.SqlServer.csproj" + "id": "Elsa.Scheduling.Hangfire", + "project": "extensions/src/scheduling/Elsa.Scheduling.Hangfire/Elsa.Scheduling.Hangfire.csproj" }, { - "id": "Elsa.UserTasks.Persistence.EFCore.Sqlite", - "project": "src/modules/Elsa.UserTasks.Persistence.EFCore.Sqlite/Elsa.UserTasks.Persistence.EFCore.Sqlite.csproj" + "id": "Elsa.Scheduling.Quartz.EFCore.MySql", + "project": "extensions/src/scheduling/Elsa.Scheduling.Quartz.EFCore.MySql/Elsa.Scheduling.Quartz.EFCore.MySql.csproj" }, { - "id": "Elsa.UserTasks.Persistence.EFCore", - "project": "src/modules/Elsa.UserTasks.Persistence.EFCore/Elsa.UserTasks.Persistence.EFCore.csproj" + "id": "Elsa.Scheduling.Quartz.EFCore.PostgreSql", + "project": "extensions/src/scheduling/Elsa.Scheduling.Quartz.EFCore.PostgreSql/Elsa.Scheduling.Quartz.EFCore.PostgreSql.csproj" }, { - "id": "Elsa.UserTasks.Persistence.VNext", - "project": "src/modules/Elsa.UserTasks.Persistence.VNext/Elsa.UserTasks.Persistence.VNext.csproj" + "id": "Elsa.Scheduling.Quartz.EFCore.SqlServer", + "project": "extensions/src/scheduling/Elsa.Scheduling.Quartz.EFCore.SqlServer/Elsa.Scheduling.Quartz.EFCore.SqlServer.csproj" }, { - "id": "Elsa.UserTasks", - "project": "src/modules/Elsa.UserTasks/Elsa.UserTasks.csproj" + "id": "Elsa.Scheduling.Quartz.EFCore.Sqlite", + "project": "extensions/src/scheduling/Elsa.Scheduling.Quartz.EFCore.Sqlite/Elsa.Scheduling.Quartz.EFCore.Sqlite.csproj" }, { - "id": "Elsa.WorkflowProviders.BlobStorage.ElsaScript", - "project": "src/modules/Elsa.WorkflowProviders.BlobStorage.ElsaScript/Elsa.WorkflowProviders.BlobStorage.ElsaScript.csproj" + "id": "Elsa.Scheduling.Quartz", + "project": "extensions/src/scheduling/Elsa.Scheduling.Quartz/Elsa.Scheduling.Quartz.csproj" }, { - "id": "Elsa.WorkflowProviders.BlobStorage", - "project": "src/modules/Elsa.WorkflowProviders.BlobStorage/Elsa.WorkflowProviders.BlobStorage.csproj" + "id": "Elsa.ServiceBus.AzureServiceBus", + "project": "extensions/src/servicebus/Elsa.ServiceBus.AzureServiceBus/Elsa.ServiceBus.AzureServiceBus.csproj" }, { - "id": "Elsa.Workflows.Api", - "project": "src/modules/Elsa.Workflows.Api/Elsa.Workflows.Api.csproj" + "id": "Elsa.ServiceBus.Kafka", + "project": "extensions/src/servicebus/Elsa.ServiceBus.Kafka/Elsa.ServiceBus.Kafka.csproj" }, { - "id": "Elsa.Workflows.Core", - "project": "src/modules/Elsa.Workflows.Core/Elsa.Workflows.Core.csproj" + "id": "Elsa.ServiceBus.MassTransit.AzureServiceBus", + "project": "extensions/src/servicebus/Elsa.ServiceBus.MassTransit.AzureServiceBus/Elsa.ServiceBus.MassTransit.AzureServiceBus.csproj" }, { - "id": "Elsa.Workflows.Management", - "project": "src/modules/Elsa.Workflows.Management/Elsa.Workflows.Management.csproj" + "id": "Elsa.ServiceBus.MassTransit.RabbitMq", + "project": "extensions/src/servicebus/Elsa.ServiceBus.MassTransit.RabbitMq/Elsa.ServiceBus.MassTransit.RabbitMq.csproj" }, { - "id": "Elsa.Workflows.Runtime.Dashboard", - "project": "src/modules/Elsa.Workflows.Runtime.Dashboard/Elsa.Workflows.Runtime.Dashboard.csproj" + "id": "Elsa.ServiceBus.MassTransit", + "project": "extensions/src/servicebus/Elsa.ServiceBus.MassTransit/Elsa.ServiceBus.MassTransit.csproj" }, { - "id": "Elsa.Workflows.Runtime.Distributed", - "project": "src/modules/Elsa.Workflows.Runtime.Distributed/Elsa.Workflows.Runtime.Distributed.csproj" + "id": "Elsa.Sql.MySql", + "project": "extensions/src/sql/Elsa.Sql.MySql/Elsa.Sql.MySql.csproj" }, { - "id": "Elsa.Workflows.Runtime", - "project": "src/modules/Elsa.Workflows.Runtime/Elsa.Workflows.Runtime.csproj" + "id": "Elsa.Sql.PostgreSql", + "project": "extensions/src/sql/Elsa.Sql.PostgreSql/Elsa.Sql.PostgreSql.csproj" }, { - "id": "Elsa", - "project": "src/modules/Elsa/Elsa.csproj" + "id": "Elsa.Sql.SqlServer", + "project": "extensions/src/sql/Elsa.Sql.SqlServer/Elsa.Sql.SqlServer.csproj" + }, + { + "id": "Elsa.Sql.Sqlite", + "project": "extensions/src/sql/Elsa.Sql.Sqlite/Elsa.Sql.Sqlite.csproj" + }, + { + "id": "Elsa.Sql", + "project": "extensions/src/sql/Elsa.Sql/Elsa.Sql.csproj" + }, + { + "id": "Elsa.Storage.AzureStorage", + "project": "extensions/src/storage/Elsa.Storage.AzureStorage/Elsa.Storage.AzureStorage.csproj" + }, + { + "id": "Elsa.Storage.Files", + "project": "extensions/src/storage/Elsa.Storage.Files/Elsa.Storage.Files.csproj" + }, + { + "id": "Elsa.Telnyx", + "project": "extensions/src/telecom/Elsa.Telnyx/Elsa.Telnyx.csproj" + }, + { + "id": "Elsa.Studio.WorkflowContexts", + "project": "extensions/src/workflows/Elsa.Studio.WorkflowContexts/Elsa.Studio.WorkflowContexts.csproj" + }, + { + "id": "Elsa.WorkflowContexts", + "project": "extensions/src/workflows/Elsa.WorkflowContexts/Elsa.WorkflowContexts.csproj" }, { "id": "Elsa.Studio", - "project": "src/studio/bundles/Elsa.Studio/Elsa.Studio.csproj" + "project": "studio/src/bundles/Elsa.Studio/Elsa.Studio.csproj" }, { "id": "Elsa.Studio.Core.BlazorServer", - "project": "src/studio/framework/Elsa.Studio.Core.BlazorServer/Elsa.Studio.Core.BlazorServer.csproj" + "project": "studio/src/framework/Elsa.Studio.Core.BlazorServer/Elsa.Studio.Core.BlazorServer.csproj" }, { "id": "Elsa.Studio.Core.BlazorWasm", - "project": "src/studio/framework/Elsa.Studio.Core.BlazorWasm/Elsa.Studio.Core.BlazorWasm.csproj" + "project": "studio/src/framework/Elsa.Studio.Core.BlazorWasm/Elsa.Studio.Core.BlazorWasm.csproj" }, { "id": "Elsa.Studio.Core", - "project": "src/studio/framework/Elsa.Studio.Core/Elsa.Studio.Core.csproj" + "project": "studio/src/framework/Elsa.Studio.Core/Elsa.Studio.Core.csproj" }, { "id": "Elsa.Studio.DomInterop", - "project": "src/studio/framework/Elsa.Studio.DomInterop/Elsa.Studio.DomInterop.csproj" + "project": "studio/src/framework/Elsa.Studio.DomInterop/Elsa.Studio.DomInterop.csproj" }, { "id": "Elsa.Studio.Shared", - "project": "src/studio/framework/Elsa.Studio.Shared/Elsa.Studio.Shared.csproj" + "project": "studio/src/framework/Elsa.Studio.Shared/Elsa.Studio.Shared.csproj" }, { "id": "Elsa.Studio.Shell", - "project": "src/studio/framework/Elsa.Studio.Shell/Elsa.Studio.Shell.csproj" + "project": "studio/src/framework/Elsa.Studio.Shell/Elsa.Studio.Shell.csproj" }, { "id": "Elsa.Studio.Translations", - "project": "src/studio/framework/Elsa.Studio.Translations/Elsa.Studio.Translations.csproj" + "project": "studio/src/framework/Elsa.Studio.Translations/Elsa.Studio.Translations.csproj" }, { "id": "Elsa.Studio.AI", - "project": "src/studio/modules/Elsa.Studio.AI/Elsa.Studio.AI.csproj" + "project": "studio/src/modules/Elsa.Studio.AI/Elsa.Studio.AI.csproj" }, { "id": "Elsa.Studio.ActivityPortProviders", - "project": "src/studio/modules/Elsa.Studio.ActivityPortProviders/Elsa.Studio.ActivityPortProviders.csproj" + "project": "studio/src/modules/Elsa.Studio.ActivityPortProviders/Elsa.Studio.ActivityPortProviders.csproj" }, { "id": "Elsa.Studio.Alterations", - "project": "src/studio/modules/Elsa.Studio.Alterations/Elsa.Studio.Alterations.csproj" + "project": "studio/src/modules/Elsa.Studio.Alterations/Elsa.Studio.Alterations.csproj" }, { "id": "Elsa.Studio.Authentication.Abstractions", - "project": "src/studio/modules/Elsa.Studio.Authentication.Abstractions/Elsa.Studio.Authentication.Abstractions.csproj" + "project": "studio/src/modules/Elsa.Studio.Authentication.Abstractions/Elsa.Studio.Authentication.Abstractions.csproj" }, { "id": "Elsa.Studio.Authentication.ElsaIdentity.BlazorServer", - "project": "src/studio/modules/Elsa.Studio.Authentication.ElsaIdentity.BlazorServer/Elsa.Studio.Authentication.ElsaIdentity.BlazorServer.csproj" + "project": "studio/src/modules/Elsa.Studio.Authentication.ElsaIdentity.BlazorServer/Elsa.Studio.Authentication.ElsaIdentity.BlazorServer.csproj" }, { "id": "Elsa.Studio.Authentication.ElsaIdentity.BlazorWasm", - "project": "src/studio/modules/Elsa.Studio.Authentication.ElsaIdentity.BlazorWasm/Elsa.Studio.Authentication.ElsaIdentity.BlazorWasm.csproj" + "project": "studio/src/modules/Elsa.Studio.Authentication.ElsaIdentity.BlazorWasm/Elsa.Studio.Authentication.ElsaIdentity.BlazorWasm.csproj" }, { "id": "Elsa.Studio.Authentication.ElsaIdentity.UI", - "project": "src/studio/modules/Elsa.Studio.Authentication.ElsaIdentity.UI/Elsa.Studio.Authentication.ElsaIdentity.UI.csproj" + "project": "studio/src/modules/Elsa.Studio.Authentication.ElsaIdentity.UI/Elsa.Studio.Authentication.ElsaIdentity.UI.csproj" }, { "id": "Elsa.Studio.Authentication.ElsaIdentity", - "project": "src/studio/modules/Elsa.Studio.Authentication.ElsaIdentity/Elsa.Studio.Authentication.ElsaIdentity.csproj" + "project": "studio/src/modules/Elsa.Studio.Authentication.ElsaIdentity/Elsa.Studio.Authentication.ElsaIdentity.csproj" }, { "id": "Elsa.Studio.Authentication.OpenIdConnect.BlazorServer", - "project": "src/studio/modules/Elsa.Studio.Authentication.OpenIdConnect.BlazorServer/Elsa.Studio.Authentication.OpenIdConnect.BlazorServer.csproj" + "project": "studio/src/modules/Elsa.Studio.Authentication.OpenIdConnect.BlazorServer/Elsa.Studio.Authentication.OpenIdConnect.BlazorServer.csproj" }, { "id": "Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm", - "project": "src/studio/modules/Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm/Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm.csproj" + "project": "studio/src/modules/Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm/Elsa.Studio.Authentication.OpenIdConnect.BlazorWasm.csproj" }, { "id": "Elsa.Studio.Authentication.OpenIdConnect", - "project": "src/studio/modules/Elsa.Studio.Authentication.OpenIdConnect/Elsa.Studio.Authentication.OpenIdConnect.csproj" + "project": "studio/src/modules/Elsa.Studio.Authentication.OpenIdConnect/Elsa.Studio.Authentication.OpenIdConnect.csproj" }, { "id": "Elsa.Studio.Authentication.Themes", - "project": "src/studio/modules/Elsa.Studio.Authentication.Themes/Elsa.Studio.Authentication.Themes.csproj" + "project": "studio/src/modules/Elsa.Studio.Authentication.Themes/Elsa.Studio.Authentication.Themes.csproj" }, { "id": "Elsa.Studio.Authentication.UI", - "project": "src/studio/modules/Elsa.Studio.Authentication.UI/Elsa.Studio.Authentication.UI.csproj" + "project": "studio/src/modules/Elsa.Studio.Authentication.UI/Elsa.Studio.Authentication.UI.csproj" }, { "id": "Elsa.Studio.Counter", - "project": "src/studio/modules/Elsa.Studio.Counter/Elsa.Studio.Counter.csproj" + "project": "studio/src/modules/Elsa.Studio.Counter/Elsa.Studio.Counter.csproj" }, { "id": "Elsa.Studio.Dashboard", - "project": "src/studio/modules/Elsa.Studio.Dashboard/Elsa.Studio.Dashboard.csproj" + "project": "studio/src/modules/Elsa.Studio.Dashboard/Elsa.Studio.Dashboard.csproj" }, { "id": "Elsa.Studio.Diagnostics.ConsoleLogs.Dashboard", - "project": "src/studio/modules/Elsa.Studio.Diagnostics.ConsoleLogs.Dashboard/Elsa.Studio.Diagnostics.ConsoleLogs.Dashboard.csproj" + "project": "studio/src/modules/Elsa.Studio.Diagnostics.ConsoleLogs.Dashboard/Elsa.Studio.Diagnostics.ConsoleLogs.Dashboard.csproj" }, { "id": "Elsa.Studio.Diagnostics.ConsoleLogs", - "project": "src/studio/modules/Elsa.Studio.Diagnostics.ConsoleLogs/Elsa.Studio.Diagnostics.ConsoleLogs.csproj" + "project": "studio/src/modules/Elsa.Studio.Diagnostics.ConsoleLogs/Elsa.Studio.Diagnostics.ConsoleLogs.csproj" }, { "id": "Elsa.Studio.Diagnostics.OpenTelemetry.Dashboard", - "project": "src/studio/modules/Elsa.Studio.Diagnostics.OpenTelemetry.Dashboard/Elsa.Studio.Diagnostics.OpenTelemetry.Dashboard.csproj" + "project": "studio/src/modules/Elsa.Studio.Diagnostics.OpenTelemetry.Dashboard/Elsa.Studio.Diagnostics.OpenTelemetry.Dashboard.csproj" }, { "id": "Elsa.Studio.Diagnostics.OpenTelemetry", - "project": "src/studio/modules/Elsa.Studio.Diagnostics.OpenTelemetry/Elsa.Studio.Diagnostics.OpenTelemetry.csproj" + "project": "studio/src/modules/Elsa.Studio.Diagnostics.OpenTelemetry/Elsa.Studio.Diagnostics.OpenTelemetry.csproj" }, { "id": "Elsa.Studio.Diagnostics.StructuredLogs.Dashboard", - "project": "src/studio/modules/Elsa.Studio.Diagnostics.StructuredLogs.Dashboard/Elsa.Studio.Diagnostics.StructuredLogs.Dashboard.csproj" + "project": "studio/src/modules/Elsa.Studio.Diagnostics.StructuredLogs.Dashboard/Elsa.Studio.Diagnostics.StructuredLogs.Dashboard.csproj" }, { "id": "Elsa.Studio.Diagnostics.StructuredLogs", - "project": "src/studio/modules/Elsa.Studio.Diagnostics.StructuredLogs/Elsa.Studio.Diagnostics.StructuredLogs.csproj" + "project": "studio/src/modules/Elsa.Studio.Diagnostics.StructuredLogs/Elsa.Studio.Diagnostics.StructuredLogs.csproj" }, { "id": "Elsa.Studio.Environments", - "project": "src/studio/modules/Elsa.Studio.Environments/Elsa.Studio.Environments.csproj" + "project": "studio/src/modules/Elsa.Studio.Environments/Elsa.Studio.Environments.csproj" }, { "id": "Elsa.Studio.ExternalAuthentication.BlazorServer", - "project": "src/studio/modules/Elsa.Studio.ExternalAuthentication.BlazorServer/Elsa.Studio.ExternalAuthentication.BlazorServer.csproj" + "project": "studio/src/modules/Elsa.Studio.ExternalAuthentication.BlazorServer/Elsa.Studio.ExternalAuthentication.BlazorServer.csproj" }, { "id": "Elsa.Studio.ExternalAuthentication.BlazorWasm", - "project": "src/studio/modules/Elsa.Studio.ExternalAuthentication.BlazorWasm/Elsa.Studio.ExternalAuthentication.BlazorWasm.csproj" + "project": "studio/src/modules/Elsa.Studio.ExternalAuthentication.BlazorWasm/Elsa.Studio.ExternalAuthentication.BlazorWasm.csproj" }, { "id": "Elsa.Studio.ExternalAuthentication", - "project": "src/studio/modules/Elsa.Studio.ExternalAuthentication/Elsa.Studio.ExternalAuthentication.csproj" + "project": "studio/src/modules/Elsa.Studio.ExternalAuthentication/Elsa.Studio.ExternalAuthentication.csproj" }, { "id": "Elsa.Studio.Http.Webhooks", - "project": "src/studio/modules/Elsa.Studio.Http.Webhooks/Elsa.Studio.Http.Webhooks.csproj" + "project": "studio/src/modules/Elsa.Studio.Http.Webhooks/Elsa.Studio.Http.Webhooks.csproj" }, { "id": "Elsa.Studio.Labels", - "project": "src/studio/modules/Elsa.Studio.Labels/Elsa.Studio.Labels.csproj" + "project": "studio/src/modules/Elsa.Studio.Labels/Elsa.Studio.Labels.csproj" }, { "id": "Elsa.Studio.Localization.BlazorServer", - "project": "src/studio/modules/Elsa.Studio.Localization.BlazorServer/Elsa.Studio.Localization.BlazorServer.csproj" + "project": "studio/src/modules/Elsa.Studio.Localization.BlazorServer/Elsa.Studio.Localization.BlazorServer.csproj" }, { "id": "Elsa.Studio.Localization.BlazorWasm", - "project": "src/studio/modules/Elsa.Studio.Localization.BlazorWasm/Elsa.Studio.Localization.BlazorWasm.csproj" + "project": "studio/src/modules/Elsa.Studio.Localization.BlazorWasm/Elsa.Studio.Localization.BlazorWasm.csproj" }, { "id": "Elsa.Studio.Localization", - "project": "src/studio/modules/Elsa.Studio.Localization/Elsa.Studio.Localization.csproj" + "project": "studio/src/modules/Elsa.Studio.Localization/Elsa.Studio.Localization.csproj" }, { "id": "Elsa.Studio.Login.BlazorServer", - "project": "src/studio/modules/Elsa.Studio.Login.BlazorServer/Elsa.Studio.Login.BlazorServer.csproj" + "project": "studio/src/modules/Elsa.Studio.Login.BlazorServer/Elsa.Studio.Login.BlazorServer.csproj" }, { "id": "Elsa.Studio.Login.BlazorWasm", - "project": "src/studio/modules/Elsa.Studio.Login.BlazorWasm/Elsa.Studio.Login.BlazorWasm.csproj" + "project": "studio/src/modules/Elsa.Studio.Login.BlazorWasm/Elsa.Studio.Login.BlazorWasm.csproj" }, { "id": "Elsa.Studio.Login", - "project": "src/studio/modules/Elsa.Studio.Login/Elsa.Studio.Login.csproj" + "project": "studio/src/modules/Elsa.Studio.Login/Elsa.Studio.Login.csproj" }, { "id": "Elsa.Studio.PlatformIntegration", - "project": "src/studio/modules/Elsa.Studio.PlatformIntegration/Elsa.Studio.PlatformIntegration.csproj" + "project": "studio/src/modules/Elsa.Studio.PlatformIntegration/Elsa.Studio.PlatformIntegration.csproj" }, { "id": "Elsa.Studio.Secrets", - "project": "src/studio/modules/Elsa.Studio.Secrets/Elsa.Studio.Secrets.csproj" + "project": "studio/src/modules/Elsa.Studio.Secrets/Elsa.Studio.Secrets.csproj" }, { "id": "Elsa.Studio.Security", - "project": "src/studio/modules/Elsa.Studio.Security/Elsa.Studio.Security.csproj" + "project": "studio/src/modules/Elsa.Studio.Security/Elsa.Studio.Security.csproj" }, { "id": "Elsa.Studio.Settings", - "project": "src/studio/modules/Elsa.Studio.Settings/Elsa.Studio.Settings.csproj" + "project": "studio/src/modules/Elsa.Studio.Settings/Elsa.Studio.Settings.csproj" }, { "id": "Elsa.Studio.UIHints", - "project": "src/studio/modules/Elsa.Studio.UIHints/Elsa.Studio.UIHints.csproj" + "project": "studio/src/modules/Elsa.Studio.UIHints/Elsa.Studio.UIHints.csproj" }, { "id": "Elsa.Studio.UserTasks", - "project": "src/studio/modules/Elsa.Studio.UserTasks/Elsa.Studio.UserTasks.csproj" + "project": "studio/src/modules/Elsa.Studio.UserTasks/Elsa.Studio.UserTasks.csproj" }, { "id": "Elsa.Studio.Workflows.Core", - "project": "src/studio/modules/Elsa.Studio.Workflows.Core/Elsa.Studio.Workflows.Core.csproj" + "project": "studio/src/modules/Elsa.Studio.Workflows.Core/Elsa.Studio.Workflows.Core.csproj" }, { "id": "Elsa.Studio.Workflows.Dashboard", - "project": "src/studio/modules/Elsa.Studio.Workflows.Dashboard/Elsa.Studio.Workflows.Dashboard.csproj" + "project": "studio/src/modules/Elsa.Studio.Workflows.Dashboard/Elsa.Studio.Workflows.Dashboard.csproj" }, { "id": "Elsa.Studio.Workflows.Designer", - "project": "src/studio/modules/Elsa.Studio.Workflows.Designer/Elsa.Studio.Workflows.Designer.csproj" + "project": "studio/src/modules/Elsa.Studio.Workflows.Designer/Elsa.Studio.Workflows.Designer.csproj" }, { "id": "Elsa.Studio.Workflows", - "project": "src/studio/modules/Elsa.Studio.Workflows/Elsa.Studio.Workflows.csproj" + "project": "studio/src/modules/Elsa.Studio.Workflows/Elsa.Studio.Workflows.csproj" } ] } diff --git a/scripts/test_validate_packages_publication_selection.py b/scripts/test_validate_packages_publication_selection.py index a80e26bdc1..2452e35256 100644 --- a/scripts/test_validate_packages_publication_selection.py +++ b/scripts/test_validate_packages_publication_selection.py @@ -20,6 +20,7 @@ ("refs/tags/2.17.0", {"nuget"}), ("refs/tags/3.10.0", {"nuget"}), ("refs/tags/3.10.0-rc1", {"nuget"}), + ("refs/tags/3.10.0-rc1", {"npm"}), ("refs/tags/3.10.0-rc1", {"feedz"}), ("refs/tags/3.10.1-preview.2", {"feedz"}), ("refs/tags/3.10.1-preview.2", {"nuget"}), @@ -31,10 +32,12 @@ # Each rejection names the reason it must be rejected for, so a case cannot pass on an unrelated error. REJECTED = ( ("refs/heads/main", {"nuget"}, "requires a release tag"), + ("refs/heads/main", {"npm"}, "requires a release tag"), ("refs/heads/3.8.5", {"nuget"}, "requires a release tag"), ("refs/tags/3.8.5", {"feedz"}, "limited to 3.10.x prerelease"), ("refs/tags/3.8.0-rc2", {"feedz"}, "limited to 3.10.x prerelease"), ("refs/tags/3.10.0", {"feedz"}, "owned by publish-consolidated-original-candidate"), + ("refs/tags/3.10.0", {"npm"}, "fail-closed"), ("refs/tags/3.10.1", {"feedz"}, "owned by publish-consolidated-original-candidate"), ("refs/tags/3.10.0", {"feedz", "nuget"}, "owned by publish-consolidated-original-candidate"), ("refs/tags/03.10.0", {"nuget"}, "canonical 3.10."), @@ -60,7 +63,13 @@ def errors(ref, selected): - return selection_errors(ref, feedz="feedz" in selected, nuget="nuget" in selected, coverage="coverage" in selected) + return selection_errors( + ref, + feedz="feedz" in selected, + nuget="nuget" in selected, + npm="npm" in selected, + coverage="coverage" in selected, + ) class SelectionErrorsTests(unittest.TestCase): @@ -95,12 +104,13 @@ def test_rejects_mismatched_selections_for_the_stated_reason(self): class SelectionScriptTests(unittest.TestCase): """The job runs the script with the ref and inputs in its environment.""" - def run_script(self, ref, feedz="false", nuget="false", coverage="false"): + def run_script(self, ref, feedz="false", nuget="false", npm="false", coverage="false"): env = { **os.environ, "REF": ref, "PUBLISH_PREVIEW_FEEDZ": feedz, "PUBLISH_NUGET": nuget, + "PUBLISH_NPM": npm, "DEPLOY_COVERAGE": coverage, } return subprocess.run([sys.executable, str(SCRIPT)], env=env, capture_output=True, text=True) diff --git a/scripts/test_validate_packages_workflow_gates.py b/scripts/test_validate_packages_workflow_gates.py index c45426148b..559cc7d994 100644 --- a/scripts/test_validate_packages_workflow_gates.py +++ b/scripts/test_validate_packages_workflow_gates.py @@ -63,9 +63,9 @@ ), ( "stable 3.10 nuget still packs", - " if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }}\n run: ./build.sh Compile+Pack", + " if: ${{ !((github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) || ((github.event_name == 'release' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/tags/3.10.0')) }}\n run: ./build.sh Compile+Pack", " run: ./build.sh Compile+Pack", - "build Compile+Pack must skip a stable 3.10.x nuget.org promotion", + "build Compile+Pack must skip a stable 3.10.x nuget.org promotion and the 3.10.0 candidate pack", ), ( "packages.yml packs the consolidated set again", @@ -123,8 +123,8 @@ ), ( "selection script sees a fixed ref", - " REF: ${{ github.ref }}\n PUBLISH_PREVIEW_FEEDZ", - " REF: refs/heads/main\n PUBLISH_PREVIEW_FEEDZ", + " REF: ${{ github.ref }}\n PUBLISH_PREVIEW_FEEDZ: ${{ inputs.publish_preview_feedz }}\n PUBLISH_NUGET: ${{ inputs.publish_nuget }}\n PUBLISH_NPM: ${{ inputs.publish_npm }}", + " REF: refs/heads/main\n PUBLISH_PREVIEW_FEEDZ: ${{ inputs.publish_preview_feedz }}\n PUBLISH_NUGET: ${{ inputs.publish_nuget }}\n PUBLISH_NPM: ${{ inputs.publish_npm }}", "validate_publication_selection must pass REF: ${{ github.ref }}", ), ( @@ -141,7 +141,7 @@ ), ( "build drops setup-dotnet", - " - uses: actions/setup-dotnet@v4\n if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }}\n with:\n dotnet-version: 10.x\n", + " - uses: actions/setup-dotnet@v4\n if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }}\n with:\n dotnet-version: |\n 8.0.x\n 9.0.x\n 10.x\n", " - uses: actions/setup-python@v5\n if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }}\n with:\n python-version: '3.12'\n", "build job must contain setup-dotnet", ), @@ -621,21 +621,21 @@ def test_candidate_recheck_rejects_always(self): def test_inverted_compile_pack_condition_is_rejected(self): source = self.mutated( " - name: Compile+Pack\n" - " if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }}\n" + " if: ${{ !((github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) || ((github.event_name == 'release' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/tags/3.10.0')) }}\n" " run: ./build.sh Compile+Pack --version \"${VERSION}\" --analyseCode true\n", " - name: Compile+Pack\n" " if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-') }}\n" " run: ./build.sh Compile+Pack --version \"${VERSION}\" --analyseCode true\n", ) - self.assert_rejected(source, "build Compile+Pack must skip a stable 3.10.x nuget.org promotion") + self.assert_rejected(source, "build Compile+Pack must skip a stable 3.10.x nuget.org promotion and the 3.10.0 candidate pack") def test_duplicate_compile_pack_is_rejected(self): source = self.mutated( " - name: Compile+Pack\n" - " if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }}\n" + " if: ${{ !((github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) || ((github.event_name == 'release' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/tags/3.10.0')) }}\n" " run: ./build.sh Compile+Pack --version \"${VERSION}\" --analyseCode true\n", " - name: Compile+Pack\n" - " if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }}\n" + " if: ${{ !((github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) || ((github.event_name == 'release' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/tags/3.10.0')) }}\n" " run: ./build.sh Compile+Pack --version \"${VERSION}\" --analyseCode true\n" "\n" " - name: Compile+Pack\n" @@ -663,9 +663,89 @@ def test_staging_condition_prefixed_with_false_is_rejected(self): def test_real_workflow_uses_the_pinned_promote_conditions(self): self.assertEqual(gates.SKIP_STABLE_310_PACK, if_expression_of_real("Compile+Pack")) + self.assertEqual(gates.CANDIDATE_PACK, if_expression_of_real("Pack consolidated 3.10.0 set")) self.assertEqual(gates.PROMOTE_STABLE_310, if_expression_of_real("Stage and guard verified candidate packages")) + self.assertEqual(gates.PROMOTE_STABLE_310, if_expression_of_real("Fail closed on stable 3.10.x")) self.assertEqual([], gates.source_violations(self.source)) + def test_candidate_pack_must_run_the_id_set_guard(self): + self.assert_rejected( + self.mutated( + " python3 scripts/integration-program/prepare_consolidated_release_candidate.py --version 3.10.0 --output \"$RUNNER_TEMP/consolidated-candidate\" --remote-sources\n" + " python3 scripts/validate_packages_id_set.py\n", + " python3 scripts/integration-program/prepare_consolidated_release_candidate.py --version 3.10.0 --output \"$RUNNER_TEMP/consolidated-candidate\" --remote-sources\n" + " true\n", + ), + "build candidate pack run: must be exactly prepare, then the ID-set guard", + ) + + def test_npm_job_must_fail_closed_on_stable_310(self): + self.assert_rejected( + self.mutated( + " - name: Fail closed on stable 3.10.x\n", + " - name: Skip closed on stable 3.10.x\n", + ), + "publish_npm must fail closed on a stable 3.10.x tag", + ) + + def test_build_npm_must_pin_setup_dotnet(self): + self.assert_rejected( + self.mutated( + " - uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1\n with:\n dotnet-version: '10.0.300'\n", + " - uses: actions/setup-dotnet@v4\n with:\n dotnet-version: 10.x\n", + ), + "build_npm must pin setup-dotnet to the studio-npm-pair SHA", + ) + + def test_build_npm_must_need_build(self): + self.assert_rejected( + self.mutated( + " build_npm:\n name: Build Studio npm pair\n needs: [build, validate_publication_selection]\n", + " build_npm:\n name: Build Studio npm pair\n needs: [validate_publication_selection]\n", + ), + "build_npm must need build", + ) + + def test_build_npm_must_set_pythondontwritebytecode(self): + self.assert_rejected( + self.mutated( + " env:\n PYTHONDONTWRITEBYTECODE: '1'\n", + "", + ), + "build_npm must set PYTHONDONTWRITEBYTECODE to 1", + ) + + def test_build_npm_must_pin_sdk_version(self): + self.assert_rejected( + self.mutated( + " dotnet-version: '10.0.300'\n", + " dotnet-version: 10.x\n", + ), + "build_npm must pin setup-dotnet to 10.0.300", + ) + + def test_publish_npm_must_not_build_the_pair(self): + self.assert_rejected( + self.mutated( + " - name: Verify Studio npm pair\n", + " - name: Build the Studio npm pair\n run: python3 scripts/integration-program/prove_studio_npm_pair.py\n\n - name: Verify Studio npm pair\n", + ), + "publish_npm must not build the Studio pair; build_npm owns that step", + ) + + def test_feedz_publish_must_pass_a_dist_tag(self): + self.assert_rejected( + self.mutated( + ' if output=$(npm publish "$file" --access public --tag "$tag" 2>&1); then\n', + ' if output=$(npm publish "$file" --access public 2>&1); then\n', + ), + "publish_npm Feedz publish must pass a dist-tag", + ) + + def test_id_set_count_is_pinned(self): + self.assertEqual([], gates.id_set_count_violations()) + self.assertEqual(231, gates.EXPECTED_PACKAGE_COUNT) + def if_expression_of_real(name: str) -> str: workflow = yaml.safe_load(gates.WORKFLOW.read_text(encoding="utf-8")) diff --git a/scripts/validate_packages_publication_selection.py b/scripts/validate_packages_publication_selection.py index 3eefa2a7b1..a86f101f3b 100644 --- a/scripts/validate_packages_publication_selection.py +++ b/scripts/validate_packages_publication_selection.py @@ -7,6 +7,7 @@ REF github.ref, e.g. refs/heads/main or refs/tags/3.10.0 PUBLISH_PREVIEW_FEEDZ inputs.publish_preview_feedz ("true" or "false") PUBLISH_NUGET inputs.publish_nuget + PUBLISH_NPM inputs.publish_npm DEPLOY_COVERAGE inputs.deploy_coverage """ @@ -26,12 +27,14 @@ COVERAGE_REFS = ("refs/heads/main", "refs/heads/release/3.6.1") -def selection_errors(ref: str, *, feedz: bool = False, nuget: bool = False, coverage: bool = False) -> list[str]: +def selection_errors(ref: str, *, feedz: bool = False, nuget: bool = False, npm: bool = False, coverage: bool = False) -> list[str]: """Return why this selection must not run; an empty list means it may.""" errors = [] if ref.startswith("refs/heads/"): if nuget: errors.append("NuGet.org publication requires a release tag ref, not a branch.") + if npm: + errors.append("Studio npm publication requires a release tag ref, not a branch.") elif ref.startswith("refs/tags/"): tag = ref[len("refs/tags/"):] if not RELEASE_TAG.fullmatch(tag): @@ -50,6 +53,8 @@ def selection_errors(ref: str, *, feedz: bool = False, nuget: bool = False, cove errors.append("Feedz publication for stable 3.10.x is owned by publish-consolidated-original-candidate.yml.") elif feedz and not feedz_from_tag: errors.append("Feedz publication from a tag is limited to 3.10.x prerelease tags; publish previews from a branch.") + if npm and is_stable_310(tag): + errors.append("Studio npm publication for stable 3.10.x stays fail-closed until the 231-ID nuget.org promote guard can pass.") else: return [f"Ref {ref!r} is neither a branch nor a tag."] if coverage and ref not in COVERAGE_REFS: @@ -70,6 +75,7 @@ def main() -> int: ref, feedz=_flag("PUBLISH_PREVIEW_FEEDZ"), nuget=_flag("PUBLISH_NUGET"), + npm=_flag("PUBLISH_NPM"), coverage=_flag("DEPLOY_COVERAGE"), ) for error in errors: diff --git a/scripts/validate_packages_workflow_gates.py b/scripts/validate_packages_workflow_gates.py index 3656f7b0d4..0100ee61d7 100644 --- a/scripts/validate_packages_workflow_gates.py +++ b/scripts/validate_packages_workflow_gates.py @@ -28,7 +28,7 @@ SELECTION_JOB = "validate_publication_selection" # Each gated job is switched on by the workflow_dispatch input of the same name. -GATED_JOBS = ("publish_preview_feedz", "publish_nuget", "deploy_coverage") +GATED_JOBS = ("publish_preview_feedz", "publish_nuget", "publish_npm", "deploy_coverage") MANUAL_DISPATCH = "github.event_name == 'workflow_dispatch'" # Top-level conjuncts a gated job's if: needs beyond the dispatch and its own input. REQUIRED_REF_CONDITIONS = { @@ -38,6 +38,9 @@ "publish_nuget": ( "startsWith(github.ref, 'refs/tags/')", ), + "publish_npm": ( + "startsWith(github.ref, 'refs/tags/')", + ), "deploy_coverage": (" || ".join(f"github.ref == '{ref}'" for ref in COVERAGE_REFS),), } SELECTION_COMMAND = "python3 scripts/validate_packages_publication_selection.py" @@ -45,6 +48,7 @@ "REF": "${{ github.ref }}", "PUBLISH_PREVIEW_FEEDZ": "${{ inputs.publish_preview_feedz }}", "PUBLISH_NUGET": "${{ inputs.publish_nuget }}", + "PUBLISH_NPM": "${{ inputs.publish_npm }}", "DEPLOY_COVERAGE": "${{ inputs.deploy_coverage }}", } # Probed against the script the selection job runs, not a copy of its rules. @@ -53,18 +57,30 @@ ("a non-release tag", "refs/tags/test-1", {}), ("Feedz from a stable 3.10.x tag", "refs/tags/3.10.0", {"feedz": True}), ("Feedz from a later stable 3.10.x tag", "refs/tags/3.10.1", {"feedz": True}), + ("npm from a stable 3.10.x tag", "refs/tags/3.10.0", {"npm": True}), ) REQUIRED_ACCEPTANCES = ( ("Feedz from a 3.10.x prerelease tag", "refs/tags/3.10.0-rc1", {"feedz": True}), ("NuGet from a stable 3.10.x tag", "refs/tags/3.10.0", {"nuget": True}), + ("npm from a 3.10.x prerelease tag", "refs/tags/3.10.0-rc1", {"npm": True}), ) PROMOTE_STABLE_REF = "startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')" +TAG_3100 = "github.ref == 'refs/tags/3.10.0'" # Exact if: bodies after ${{ }} unwrap. Substring checks miss polarity # (inverted Compile+Pack) and a leading `false &&` (disabled staging). -SKIP_STABLE_310_PACK = ( +SKIP_STABLE_310_PROMOTE = ( "!(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && " f"{PROMOTE_STABLE_REF})" ) +SKIP_STABLE_310_PACK = ( + "!((github.event_name == 'workflow_dispatch' && inputs.publish_nuget && " + f"{PROMOTE_STABLE_REF}) || ((github.event_name == 'release' || " + f"github.event_name == 'workflow_dispatch') && {TAG_3100}))" +) +CANDIDATE_PACK = ( + f"(github.event_name == 'release' || github.event_name == 'workflow_dispatch') && " + f"{TAG_3100} && !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget)" +) PROMOTE_STABLE_310 = PROMOTE_STABLE_REF SKIP_STABLE_310_DOWNLOAD = f"!({PROMOTE_STABLE_REF})" UPLOAD_PACKAGES = ( @@ -76,6 +92,21 @@ RETRIEVE_CANDIDATE = "python3 scripts/stage_consolidated_candidate_nupkgs.py retrieve" STAGE_CANDIDATE = "python3 scripts/stage_consolidated_candidate_nupkgs.py stage" GUARD_CANDIDATE = "python3 scripts/validate_packages_id_set.py" +PREPARE_CANDIDATE = "python3 scripts/integration-program/prepare_consolidated_release_candidate.py" +CANDIDATE_PACK_LINES = ( + "set -euo pipefail", + f"{PREPARE_CANDIDATE} --version 3.10.0 --output \"$RUNNER_TEMP/consolidated-candidate\" --remote-sources", + GUARD_CANDIDATE, +) +NPM_PAIR = "python3 scripts/integration-program/prove_studio_npm_pair.py" +BUILD_NPM_JOB = "build_npm" +SETUP_DOTNET_PIN = "actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9" +DOTNET_SDK = "10.0.300" +NPM_ARTIFACT = "studio-npm-pair" +WASM_TGZ = "elsa-workflows-elsa-studio-wasm-${GITHUB_REF_NAME}.tgz" +REACT_TGZ = "elsa-workflows-elsa-studio-wasm-react-${GITHUB_REF_NAME}.tgz" +ID_SET = ROOT / "scripts/validate_packages_id_set.txt" +EXPECTED_PACKAGE_COUNT = 231 # Exact non-empty run: lines after horizontal-whitespace collapse. A joined # string would accept YAML `>-`, which folds the block into one no-op `set`. CANDIDATE_GUARD_LINES = ("set -euo pipefail", STAGE_CANDIDATE, GUARD_CANDIDATE) @@ -95,6 +126,7 @@ "actions/deploy-pages": re.compile(r"\bactions/deploy-pages\b", re.IGNORECASE), "dotnet nuget push": re.compile(r"\bdotnet[\s\\]+nuget[\s\\]+push\b", re.IGNORECASE), "the push-nuget-packages action": re.compile(r"push-nuget-packages", re.IGNORECASE), + "npm publish": re.compile(r"\bnpm[\s\\]+publish\b", re.IGNORECASE), } EXPRESSION = re.compile(r"\$\{\{(.*?)\}\}", re.DOTALL) # Inside ${{ }}: the secrets context as a whole, e.g. toJSON(secrets), which carries every feed key. @@ -467,13 +499,169 @@ def promotion_job_violations(jobs: dict) -> list[str]: ) violations += extra if compile_step is not None and if_expression(build_steps[compile_step].get("if")) != SKIP_STABLE_310_PACK: - violations.append("build Compile+Pack must skip a stable 3.10.x nuget.org promotion") - if setup_dotnet is not None and if_expression(build_steps[setup_dotnet].get("if")) != SKIP_STABLE_310_PACK: + violations.append("build Compile+Pack must skip a stable 3.10.x nuget.org promotion and the 3.10.0 candidate pack") + if setup_dotnet is not None and if_expression(build_steps[setup_dotnet].get("if")) != SKIP_STABLE_310_PROMOTE: violations.append("build setup-dotnet must skip a stable 3.10.x nuget.org promotion") - if setup_node is not None and if_expression(build_steps[setup_node].get("if")) != SKIP_STABLE_310_PACK: + if setup_node is not None and if_expression(build_steps[setup_node].get("if")) != SKIP_STABLE_310_PROMOTE: violations.append("build Node setup must skip a stable 3.10.x nuget.org promotion") if upload is not None and if_expression(build_steps[upload].get("if")) != UPLOAD_PACKAGES: violations.append("build Upload artifact must skip a stable 3.10.x nuget.org promotion") + pack, extra = _unique_step( + build_steps, + lambda step: PREPARE_CANDIDATE in _step_run(step), + missing="build job must pack the 3.10.0 set via prepare_consolidated_release_candidate.py", + duplicate="build job must contain exactly one consolidated candidate pack step", + ) + violations += extra + if pack is not None: + if if_expression(build_steps[pack].get("if")) != CANDIDATE_PACK: + violations.append("build candidate pack if: must be the 3.10.0 tag pack condition") + if _run_lines(build_steps[pack]) != list(CANDIDATE_PACK_LINES): + violations.append("build candidate pack run: must be exactly prepare, then the ID-set guard") + if GUARD_CANDIDATE not in _step_run(build_steps[pack]): + violations.append("build candidate pack must run the ID-set guard") + return violations + + +def id_set_count_violations() -> list[str]: + ids = [ + line.strip() + for line in ID_SET.read_text(encoding="utf-8").splitlines() + if line.strip() and not line.startswith("#") + ] + if len(ids) != EXPECTED_PACKAGE_COUNT: + return [f"validate_packages_id_set.txt must list exactly {EXPECTED_PACKAGE_COUNT} package IDs"] + return [] + + +def _dotnet_version(step: dict) -> str: + value = (step.get("with") or {}).get("dotnet-version") if isinstance(step.get("with"), dict) else None + if isinstance(value, list): + value = "\n".join(str(item) for item in value) + return " ".join(str(value or "").split()) + + +def build_npm_violations(jobs: dict) -> list[str]: + """The Studio npm pair is built without credentials and uploaded for publish_npm.""" + job = jobs.get(BUILD_NPM_JOB) + if not isinstance(job, dict): + return ["job 'build_npm' is missing"] + violations = [] + if BUILD_JOB not in needs(job): + violations.append("build_npm must need build") + if SELECTION_JOB not in needs(job): + violations.append("build_npm must need validate_publication_selection") + env = job.get("env") if isinstance(job.get("env"), dict) else {} + if str(env.get("PYTHONDONTWRITEBYTECODE") or "") != "1": + violations.append("build_npm must set PYTHONDONTWRITEBYTECODE to 1") + if grants_id_token(job.get("permissions")): + violations.append("build_npm must not request id-token: write") + steps = [step for step in job.get("steps") or [] if isinstance(step, dict)] + if any(node.get("continue-on-error") not in (None, False) for node in (job, *steps)): + violations.append("build_npm must not continue on error") + if any(re.search(r"\bnpm[\s\\]+publish\b", _step_run(step), re.IGNORECASE) for step in steps): + violations.append("build_npm must not publish") + setup, extra = _unique_step( + steps, + lambda step: str(step.get("uses") or "").startswith("actions/setup-dotnet@"), + missing="build_npm must pin setup-dotnet to 10.0.300", + duplicate="build_npm must contain exactly one setup-dotnet step", + ) + violations += extra + if setup is not None: + uses = str(steps[setup].get("uses") or "") + if uses != SETUP_DOTNET_PIN: + violations.append("build_npm must pin setup-dotnet to the studio-npm-pair SHA") + if _dotnet_version(steps[setup]) != DOTNET_SDK: + violations.append("build_npm must pin setup-dotnet to 10.0.300") + build_pair, extra = _unique_step( + steps, + lambda step: NPM_PAIR in _step_run(step), + missing="build_npm must build the Studio pair via prove_studio_npm_pair.py", + duplicate="build_npm must contain exactly one Studio pair build step", + ) + violations += extra + upload, extra = _unique_step( + steps, + lambda step: str(step.get("uses") or "").startswith("actions/upload-artifact@") + and str((step.get("with") or {}).get("name") or "") == NPM_ARTIFACT, + missing="build_npm must upload the studio-npm-pair artifact", + duplicate="build_npm must contain exactly one studio-npm-pair upload", + ) + violations += extra + if None not in (build_pair, upload) and not build_pair < upload: + violations.append("build_npm must build the pair before uploading it") + return violations + + +def npm_job_violations(jobs: dict) -> list[str]: + """The Studio npm publisher downloads the pair and publishes only to Feedz.""" + job = jobs.get("publish_npm") + if not isinstance(job, dict): + return ["gated job 'publish_npm' is missing"] + violations = [] + if BUILD_NPM_JOB not in needs(job): + violations.append("publish_npm must need build_npm so it publishes the credential-free pair artifact") + if grants_id_token(job.get("permissions")): + violations.append("publish_npm must not request id-token: write until trusted publishing is confirmed") + steps = [step for step in job.get("steps") or [] if isinstance(step, dict)] + if any(node.get("continue-on-error") not in (None, False) for node in (job, *steps)): + violations.append("publish_npm must not continue on error") + if any(NPM_PAIR in _step_run(step) for step in steps): + violations.append("publish_npm must not build the Studio pair; build_npm owns that step") + if any(str(step.get("uses") or "").startswith("actions/setup-dotnet@") for step in steps): + violations.append("publish_npm must not install a .NET SDK; build_npm owns that step") + closed, extra = _unique_step( + steps, + lambda step: step.get("name") == "Fail closed on stable 3.10.x", + missing="publish_npm must fail closed on a stable 3.10.x tag", + duplicate="publish_npm must contain exactly one stable 3.10.x fail-closed step", + ) + violations += extra + if closed is not None: + if if_expression(steps[closed].get("if")) != PROMOTE_STABLE_310: + violations.append("publish_npm fail-closed if: must be exactly the stable 3.10.x tag condition") + if "exit 1" not in _step_run(steps[closed]): + violations.append("publish_npm fail-closed step must exit 1") + if STATUS_FUNCTION.search(if_expression(steps[closed].get("if")) or ""): + violations.append("publish_npm fail-closed step must not call always(), failure() or cancelled()") + download, extra = _unique_step( + steps, + lambda step: str(step.get("uses") or "").startswith("actions/download-artifact@") + and str((step.get("with") or {}).get("name") or "") == NPM_ARTIFACT, + missing="publish_npm must download the studio-npm-pair artifact", + duplicate="publish_npm must contain exactly one studio-npm-pair download", + ) + violations += extra + verify, extra = _unique_step( + steps, + lambda step: WASM_TGZ in _step_run(step) and REACT_TGZ in _step_run(step), + missing="publish_npm must verify the two Studio npm tarballs at the tag version", + duplicate="publish_npm must contain exactly one Studio npm pair verify step", + ) + violations += extra + feedz_publish, extra = _unique_step( + steps, + lambda step: step.get("name") == "npm publish to Feedz", + missing="publish_npm must contain npm publish to Feedz", + duplicate="publish_npm must contain exactly one Feedz npm publish step", + ) + violations += extra + if feedz_publish is not None: + run = _step_run(steps[feedz_publish]) + if not re.search(r"\bnpm[\s\\]+publish\b.*--tag", run): + violations.append("publish_npm Feedz publish must pass a dist-tag") + if "EPUBLISHCONFLICT" not in run or "cannot publish over" not in run: + violations.append("publish_npm Feedz publish must skip a version that already exists") + if "::error::" not in run: + violations.append("publish_npm Feedz publish must fail closed when the Feedz key is empty") + publishes = [index for index, step in enumerate(steps) if re.search(r"\bnpm[\s\\]+publish\b", _step_run(step), re.IGNORECASE)] + if len(publishes) != 1: + violations.append("publish_npm must contain exactly one npm publish step") + if any(step.get("name") == "npm publish to npmjs.com" or re.search(r"registry\.npmjs\.(org|com)", _step_run(step)) for step in steps): + violations.append("publish_npm must not publish to npmjs.com until trusted publishing is confirmed") + if None not in (closed, download, verify, feedz_publish) and not closed < download < verify < feedz_publish: + violations.append("publish_npm must fail closed on stable 3.10.x, download and verify the pair, then publish to Feedz") return violations @@ -572,6 +760,8 @@ def workflow_violations(workflow: Any) -> list[str]: *selection_violations(jobs), *pages_upload_violations(jobs), *promotion_job_violations(jobs), + *build_npm_violations(jobs), + *npm_job_violations(jobs), *defaults, ] @@ -585,6 +775,7 @@ def source_violations(source: str) -> list[str]: def main() -> int: violations = [ + *(f"{ID_SET.relative_to(ROOT)}: {violation}" for violation in id_set_count_violations()), *(f"{WORKFLOW.relative_to(ROOT)}: {violation}" for violation in source_violations(WORKFLOW.read_text(encoding="utf-8"))), *( f"{CANDIDATE_WORKFLOW.relative_to(ROOT)}: {violation}" @@ -595,7 +786,7 @@ def main() -> int: print(violation, file=sys.stderr) if violations: return 1 - print("Package publication gates hold: only the three default-off, validated dispatch jobs can publish or deploy.") + print("Package publication gates hold: only the four default-off, validated dispatch jobs can publish or deploy.") return 0