From 8a568117df4429573e3dac1f883fa61f2125f695 Mon Sep 17 00:00:00 2001 From: Jaap-Jan de Wit | DodoTech Date: Sat, 1 Aug 2026 13:40:12 +0200 Subject: [PATCH] Give the API an image, and unbreak the restore that had to run first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit registry-docker.dodotech.cloud/dodotech/dodossh-api, built and pushed by a third ci job that needs the first. Gating on the tests costs a few minutes on every main commit and buys the only thing worth having here: an image is not an artefact somebody inspects before using it, so a red commit must not be able to produce one. Pull requests build the image and stop, which is where a broken Dockerfile should be found. Tags are :sha- on every build, :main on main, and for a v* tag :1.2.3, :1.2 and :latest — the last two only when the version has no prerelease suffix, since v1.3.0-rc1 sorts above v1.2.9 and would otherwise walk :latest onto somebody's server. Only sha- is immutable, and it is the one to pin a deployment to. No docker/* actions. The build is single-architecture, so it needs the daemon this runner already has for the Testcontainers suites and nothing else — no buildx, no QEMU, and no third-party action whose SHA has to be audited and re-pinned. Step outputs and secrets reach the shell through env rather than ${{ }} interpolation, because a git tag may contain a semicolon and interpolation is textual substitution performed before the shell parses the line. The image is chiseled: no shell, no package manager, uid 1654. Affordable because Directory.Build.props already sets InvariantGlobalization, so the ICU and tzdata a normal base carries are exactly what this product decided not to use. The cost is stated in the Dockerfile rather than hidden — there is no HEALTHCHECK, because there is nothing to run one with, and /healthz/ready is anonymous precisely so the orchestrator can ask instead. Nothing migrates the schema from inside the container either; readiness fails while a migration is pending and names it, which is the design. And the restore that all of this depends on did not work. 7a3a521 committed lock files carrying a net10.0/android-arm64 section into fourteen projects — written there by the Android head's -p:RuntimeIdentifier=android-arm64 packaging build, which restores the shared projects with a RID and updates their lock files as a side effect. Any restore without that RID then fails NU1004 in locked mode, which is every other build there is: `dotnet restore DodoSSH.slnx --locked-mode` has been failing for eleven projects on a clean checkout of main since that commit. The sections are removed here and nothing else changed — deletions only, ILLink.Tasks stays at 10.0.10. Verified: the solution restores in locked mode, the image builds, and it runs. /healthz/live answers 200 and /healthz/ready answers 503 naming the database it cannot reach, from a 67 MB image as uid 1654, configured entirely through DODOSSH_-prefixed variables. The Android head's own lock file still carries the RID and is untouched, because that job restores it separately and is outside DodoSSH.slnx. Whether its packaging step re-dirties these fourteen on every CI run is worth a look; it is the same mechanism. Co-Authored-By: Claude Opus 5 (1M context) --- .dockerignore | 33 +++++ .github/workflows/ci.yml | 123 ++++++++++++++++++ src/DodoSSH.Api/Dockerfile | 109 ++++++++++++++++ src/DodoSSH.Client.Api/packages.lock.json | 8 -- src/DodoSSH.Client.Auth/packages.lock.json | 3 +- src/DodoSSH.Client.Domain/packages.lock.json | 3 +- src/DodoSSH.Client.Import/packages.lock.json | 3 +- .../packages.lock.json | 8 -- src/DodoSSH.Client.Session/packages.lock.json | 14 -- src/DodoSSH.Client.Shell/packages.lock.json | 14 -- src/DodoSSH.Client.Ssh/packages.lock.json | 8 -- src/DodoSSH.Client.Storage/packages.lock.json | 14 -- src/DodoSSH.Client.Sync/packages.lock.json | 14 -- .../packages.lock.json | 8 -- .../packages.lock.json | 8 -- src/DodoSSH.Contracts/packages.lock.json | 3 +- src/DodoSSH.Crypto/packages.lock.json | 8 -- 17 files changed, 269 insertions(+), 112 deletions(-) create mode 100644 .dockerignore create mode 100644 src/DodoSSH.Api/Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3ddfcf0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,33 @@ +# The build context for src/DodoSSH.Api/Dockerfile is the repository root, because central +# package management puts Directory.Packages.props there. That makes this file matter more +# than it usually does: without it the context is the whole working tree, including every +# bin/ and obj/ directory and the Android head's build output. +# +# Excluding obj/ is not only about size. A host obj/ carries project.assets.json and the +# generated .nuget.g.props naming absolute host paths; copied into the image it overrides +# the restore that just ran inside it, and the failure surfaces as packages "not found" +# that are plainly present. + +**/bin/ +**/obj/ +artifacts/ +.git/ +.github/ +.gitea/ +.idea/ +.vs/ +.vscode/ + +# No project outside the API's reference closure contributes to this image. Listing them +# keeps a context change from silently invalidating the COPY src/ layer on every commit to +# a head this image does not contain. +src/DodoSSH.Client.*/ +tests/ +docs/ +deploy/ + +*.md +*.user +*.binlog +Dockerfile* +.dockerignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ad6c98..5d83f64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,10 @@ name: ci on: push: branches: [main] + # Release tags run the whole workflow, not only the image job that gates on it. A tag + # is the one build nobody is watching, so it is the last place to take the tests on + # trust. + tags: ['v*'] pull_request: branches: [main] @@ -100,3 +104,122 @@ jobs: dotnet build src/DodoSSH.Client.Android/DodoSSH.Client.Android.csproj --no-restore --configuration Release -t:SignAndroidPackage -p:RuntimeIdentifier=android-arm64 + + image: + name: api image + # Gated on the tests rather than parallel with them, which costs a few minutes of wall + # clock on every main commit and buys the thing worth having: no image reaches the + # registry from a commit whose tests were red. An image is not a build artefact anyone + # inspects — it is the thing that gets deployed. + needs: [build] + runs-on: [linux] + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + # No docker/* actions here, deliberately. The build is single-architecture, so it + # needs the daemon this runner already has for the Testcontainers suites and nothing + # else — no buildx plugin, no QEMU, and no third-party action whose SHA has to be + # audited and re-pinned. Adding linux/arm64 later is where that trade changes. + - name: work out the tags + id: tags + env: + REGISTRY: registry-docker.dodotech.cloud + IMAGE: dodotech/dodossh-api + run: | + set -euo pipefail + repo="$REGISTRY/$IMAGE" + short="$(git rev-parse --short HEAD)" + + # sha- prefixed, because a bare hex tag is ambiguous with a digest to both a human + # and a fair amount of tooling. This one is on every build and never moves, which + # makes it the only tag safe to pin a deployment to. + tags="$repo:sha-$short" + version="$short" + + case "$GITHUB_REF" in + refs/tags/v*) + v="${GITHUB_REF#refs/tags/v}" + version="$v" + tags="$tags $repo:$v" + # The moving major.minor tag and :latest, but only for a release proper. + # v1.3.0-rc1 sorts after v1.2.9 and would otherwise take :latest with it, + # which is how a release candidate ends up on somebody's server. + case "$v" in + *-*) ;; + *) + tags="$tags $repo:${v%.*}" + tags="$tags $repo:latest" + ;; + esac + ;; + refs/heads/main) + tags="$tags $repo:main" + version="main-$short" + ;; + esac + + echo "tags=$tags" >> "$GITHUB_OUTPUT" + echo "version=$version" >> "$GITHUB_OUTPUT" + echo "created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT" + echo "Tagging: $tags" + + # Every value from a step output or the event goes through env rather than being + # interpolated into the script text. A git tag may contain a semicolon, and + # `${{ }}` is a textual substitution performed before the shell ever sees the line — + # so an interpolated tag name is a command the workflow agreed to run. + - name: build the image + env: + TAGS: ${{ steps.tags.outputs.tags }} + VERSION: ${{ steps.tags.outputs.version }} + REVISION: ${{ github.sha }} + CREATED: ${{ steps.tags.outputs.created }} + run: | + set -euo pipefail + args=() + for tag in $TAGS; do + args+=(--tag "$tag") + done + # --pull rather than whatever the runner happens to have cached: the base images + # are floating tags, and a runner that has held aspnet:10.0-noble-chiseled for a + # month is a month of unapplied CVE fixes shipping in every image built on it. + docker build \ + --pull \ + --file src/DodoSSH.Api/Dockerfile \ + --build-arg "VERSION=$VERSION" \ + --build-arg "REVISION=$REVISION" \ + --build-arg "CREATED=$CREATED" \ + "${args[@]}" \ + . + + # Everything above runs on a pull request too. Building a fork's Dockerfile is safe — + # nothing is pushed and no credential is in scope — and it means a change that breaks + # the image fails on the PR rather than on main. Only these last two steps are held + # back, and the condition is on the event rather than on the branch so that a PR + # targeting main cannot reach them. + - name: log in to the registry + if: github.event_name != 'pull_request' + env: + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} + run: | + set -euo pipefail + printf '%s' "$REGISTRY_PASSWORD" \ + | docker login registry-docker.dodotech.cloud \ + --username "$REGISTRY_USERNAME" --password-stdin + + - name: push + if: github.event_name != 'pull_request' + env: + TAGS: ${{ steps.tags.outputs.tags }} + run: | + set -euo pipefail + for tag in $TAGS; do + docker push "$tag" + done + + # The daemon is shared with every other job on this runner, and a credential left in + # ~/.docker/config.json outlives the job that created it. always(), so a failed push + # does not leave it behind. + - name: log out + if: always() && github.event_name != 'pull_request' + run: docker logout registry-docker.dodotech.cloud diff --git a/src/DodoSSH.Api/Dockerfile b/src/DodoSSH.Api/Dockerfile new file mode 100644 index 0000000..eeeeb0d --- /dev/null +++ b/src/DodoSSH.Api/Dockerfile @@ -0,0 +1,109 @@ +# The API image. Built from the repository root, not from this directory: +# +# docker build -f src/DodoSSH.Api/Dockerfile . +# +# Directory.Build.props, Directory.Packages.props, NuGet.config and global.json all sit at +# the root and all four are load-bearing here — central package management means a csproj +# alone does not name a single version, and a build that cannot see them resolves nothing. + +# --------------------------------------------------------------------------------------- +# Build +# --------------------------------------------------------------------------------------- +FROM mcr.microsoft.com/dotnet/sdk:10.0-noble AS build + +# Reproducible builds. Directory.Build.props turns ContinuousIntegrationBuild on when this +# is set, which is what normalises the source paths baked into the PDBs — without it two +# builds of the same commit differ by the directory they happened in. +ENV CI=true \ + DOTNET_NOLOGO=true \ + DOTNET_CLI_TELEMETRY_OPTOUT=true \ + DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true + +WORKDIR /src + +# The manifests first, and only the manifests. This layer is what makes an ordinary code +# change a ten-second rebuild instead of a full package restore: it is invalidated by a +# dependency change and by nothing else. Every project in DodoSSH.Api's reference closure +# has to be here — restore walks ProjectReference, and a missing csproj fails the graph +# rather than skipping a node. +COPY global.json NuGet.config Directory.Build.props Directory.Packages.props ./ +COPY src/DodoSSH.Api/DodoSSH.Api.csproj src/DodoSSH.Api/ +COPY src/DodoSSH.Api/packages.lock.json src/DodoSSH.Api/ +COPY src/DodoSSH.Contracts/DodoSSH.Contracts.csproj src/DodoSSH.Contracts/ +COPY src/DodoSSH.Contracts/packages.lock.json src/DodoSSH.Contracts/ +COPY src/DodoSSH.Crypto/DodoSSH.Crypto.csproj src/DodoSSH.Crypto/ +COPY src/DodoSSH.Crypto/packages.lock.json src/DodoSSH.Crypto/ +COPY src/DodoSSH.Domain/DodoSSH.Domain.csproj src/DodoSSH.Domain/ +COPY src/DodoSSH.Domain/packages.lock.json src/DodoSSH.Domain/ +COPY src/DodoSSH.Infrastructure/DodoSSH.Infrastructure.csproj src/DodoSSH.Infrastructure/ +COPY src/DodoSSH.Infrastructure/packages.lock.json src/DodoSSH.Infrastructure/ + +# Locked mode here for the same reason CI uses it: the lock files are committed, so a +# dependency that changed without its lock file being reviewed fails the build rather than +# quietly shipping. An image is the one place that matters most. +RUN dotnet restore src/DodoSSH.Api/DodoSSH.Api.csproj --locked-mode + +# BannedSymbols.txt is an AdditionalFiles entry in Directory.Build.props. Without it the +# BannedApiAnalyzers rules silently pass, and with TreatWarningsAsErrors the whole point of +# the list is that it fails a build — so its absence would be invisible in exactly the way +# it is meant to prevent. +COPY BannedSymbols.txt .editorconfig ./ +COPY src/ src/ + +RUN dotnet publish src/DodoSSH.Api/DodoSSH.Api.csproj \ + --no-restore \ + --configuration Release \ + --output /app \ + -p:UseAppHost=false + +# --------------------------------------------------------------------------------------- +# Runtime +# --------------------------------------------------------------------------------------- +# +# Chiseled: no shell, no package manager, no libc utilities, and a non-root user (uid 1654) +# already set by the base image. That closes off `docker exec sh` on a process that holds a +# database connection and the cursor signing key, and it is affordable here specifically +# because Directory.Build.props sets InvariantGlobalization — the ICU and tzdata a normal +# base carries are exactly what this product has already decided it does not use. +# +# The cost is real and worth stating: there is no HEALTHCHECK below, because there is no +# curl and nothing to run one with. The health endpoints exist and are anonymous — +# /healthz/live, /healthz/ready, /healthz/startup — so the probe belongs in whatever runs +# the container. Readiness is not decoration on this API: it fails while an EF migration is +# pending and names the one it is waiting for, which is the intended way to discover that a +# deployment shipped ahead of its schema. +FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble-chiseled AS final + +# Passed by CI; see .github/workflows/ci.yml. Declared with empty defaults so a local +# `docker build` with no arguments still succeeds. +ARG VERSION="" +ARG REVISION="" +ARG CREATED="" + +LABEL org.opencontainers.image.title="DodoSSH API" \ + org.opencontainers.image.description="DodoSSH server: sync, identity, teams and relay authorization." \ + org.opencontainers.image.vendor="DodoTech" \ + org.opencontainers.image.licenses="MIT" \ + org.opencontainers.image.source="https://git.dodotech.cloud/DodoTech/DodoSSH" \ + org.opencontainers.image.version="${VERSION}" \ + org.opencontainers.image.revision="${REVISION}" \ + org.opencontainers.image.created="${CREATED}" + +WORKDIR /app +COPY --from=build /app . + +# 8080 is the .NET container default (ASPNETCORE_HTTP_PORTS in the base image), and plain +# HTTP is deliberate: Program.cs has no UseHttpsRedirection because the API is always behind +# a proxy that terminates TLS, and redirecting from here would loop. +EXPOSE 8080 + +# Configuration reaches the process two ways, both already wired in Program.cs: environment +# variables prefixed DODOSSH_, and files under /run/secrets for anything that should not be +# readable in `docker inspect`. The three the process will not start or run correctly +# without are DODOSSH_ConnectionStrings__Postgres, DODOSSH_Oidc__Authority and — on more +# than one node — DODOSSH_Sync__CursorSigningKey. +# +# Nothing migrates the database from in here. That is the API's own design: it fails +# /healthz/ready while a migration is pending and names it, so the schema is applied by +# `dotnet ef database update` alongside the deployment rather than by a racing container. +ENTRYPOINT ["dotnet", "DodoSSH.Api.dll"] diff --git a/src/DodoSSH.Client.Api/packages.lock.json b/src/DodoSSH.Client.Api/packages.lock.json index b82257b..8d54521 100644 --- a/src/DodoSSH.Client.Api/packages.lock.json +++ b/src/DodoSSH.Client.Api/packages.lock.json @@ -41,14 +41,6 @@ "libsodium": "[1.0.22, 1.0.23)" } } - }, - "net10.0/android-arm64": { - "libsodium": { - "type": "CentralTransitive", - "requested": "[1.0.22, )", - "resolved": "1.0.22", - "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" - } } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.Auth/packages.lock.json b/src/DodoSSH.Client.Auth/packages.lock.json index 6bc156e..f70ba7f 100644 --- a/src/DodoSSH.Client.Auth/packages.lock.json +++ b/src/DodoSSH.Client.Auth/packages.lock.json @@ -14,7 +14,6 @@ "resolved": "5.6.0", "contentHash": "Kcobt3pnOdO0A+6CKiMHZdTEluJpsfxiV20axtZdmfBQnDmiWTKPJADlgAfdTuKNAnVarrkJa0UEGwuOo91muw==" } - }, - "net10.0/android-arm64": {} + } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.Domain/packages.lock.json b/src/DodoSSH.Client.Domain/packages.lock.json index 6bc156e..f70ba7f 100644 --- a/src/DodoSSH.Client.Domain/packages.lock.json +++ b/src/DodoSSH.Client.Domain/packages.lock.json @@ -14,7 +14,6 @@ "resolved": "5.6.0", "contentHash": "Kcobt3pnOdO0A+6CKiMHZdTEluJpsfxiV20axtZdmfBQnDmiWTKPJADlgAfdTuKNAnVarrkJa0UEGwuOo91muw==" } - }, - "net10.0/android-arm64": {} + } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.Import/packages.lock.json b/src/DodoSSH.Client.Import/packages.lock.json index 05c5d79..a11804f 100644 --- a/src/DodoSSH.Client.Import/packages.lock.json +++ b/src/DodoSSH.Client.Import/packages.lock.json @@ -17,7 +17,6 @@ "dodossh.client.domain": { "type": "Project" } - }, - "net10.0/android-arm64": {} + } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.ObjectStore/packages.lock.json b/src/DodoSSH.Client.ObjectStore/packages.lock.json index 08c7f37..99de2a2 100644 --- a/src/DodoSSH.Client.ObjectStore/packages.lock.json +++ b/src/DodoSSH.Client.ObjectStore/packages.lock.json @@ -83,14 +83,6 @@ "Microsoft.Extensions.Logging.Abstractions": "8.0.3" } } - }, - "net10.0/android-arm64": { - "libsodium": { - "type": "CentralTransitive", - "requested": "[1.0.22, )", - "resolved": "1.0.22", - "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" - } } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.Session/packages.lock.json b/src/DodoSSH.Client.Session/packages.lock.json index 61c6203..0b12ecc 100644 --- a/src/DodoSSH.Client.Session/packages.lock.json +++ b/src/DodoSSH.Client.Session/packages.lock.json @@ -291,20 +291,6 @@ "Microsoft.Extensions.Logging.Abstractions": "8.0.3" } } - }, - "net10.0/android-arm64": { - "libsodium": { - "type": "CentralTransitive", - "requested": "[1.0.22, )", - "resolved": "1.0.22", - "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" - }, - "SQLitePCLRaw.lib.e_sqlite3": { - "type": "CentralTransitive", - "requested": "[2.1.12, )", - "resolved": "2.1.12", - "contentHash": "fWi8Dbknuhgg72fWinIdjXVaqO1hHL4YBBwVLnr7e1c9TAZwJ0QE38j9syW1hwx6HaqEVTwI+O07WPdZn8Rp0w==" - } } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.Shell/packages.lock.json b/src/DodoSSH.Client.Shell/packages.lock.json index ad198a7..c3f199a 100644 --- a/src/DodoSSH.Client.Shell/packages.lock.json +++ b/src/DodoSSH.Client.Shell/packages.lock.json @@ -371,20 +371,6 @@ "Microsoft.Extensions.Logging.Abstractions": "8.0.3" } } - }, - "net10.0/android-arm64": { - "libsodium": { - "type": "CentralTransitive", - "requested": "[1.0.22, )", - "resolved": "1.0.22", - "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" - }, - "SQLitePCLRaw.lib.e_sqlite3": { - "type": "CentralTransitive", - "requested": "[2.1.12, )", - "resolved": "2.1.12", - "contentHash": "fWi8Dbknuhgg72fWinIdjXVaqO1hHL4YBBwVLnr7e1c9TAZwJ0QE38j9syW1hwx6HaqEVTwI+O07WPdZn8Rp0w==" - } } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.Ssh/packages.lock.json b/src/DodoSSH.Client.Ssh/packages.lock.json index e5c55f8..fdf5787 100644 --- a/src/DodoSSH.Client.Ssh/packages.lock.json +++ b/src/DodoSSH.Client.Ssh/packages.lock.json @@ -58,14 +58,6 @@ "resolved": "1.0.22", "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" } - }, - "net10.0/android-arm64": { - "libsodium": { - "type": "CentralTransitive", - "requested": "[1.0.22, )", - "resolved": "1.0.22", - "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" - } } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.Storage/packages.lock.json b/src/DodoSSH.Client.Storage/packages.lock.json index cfebbd2..0b7ddce 100644 --- a/src/DodoSSH.Client.Storage/packages.lock.json +++ b/src/DodoSSH.Client.Storage/packages.lock.json @@ -395,20 +395,6 @@ "SQLitePCLRaw.core": "2.1.12" } } - }, - "net10.0/android-arm64": { - "libsodium": { - "type": "CentralTransitive", - "requested": "[1.0.22, )", - "resolved": "1.0.22", - "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" - }, - "SQLitePCLRaw.lib.e_sqlite3": { - "type": "CentralTransitive", - "requested": "[2.1.12, )", - "resolved": "2.1.12", - "contentHash": "fWi8Dbknuhgg72fWinIdjXVaqO1hHL4YBBwVLnr7e1c9TAZwJ0QE38j9syW1hwx6HaqEVTwI+O07WPdZn8Rp0w==" - } } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.Sync/packages.lock.json b/src/DodoSSH.Client.Sync/packages.lock.json index 8971da3..76eefc2 100644 --- a/src/DodoSSH.Client.Sync/packages.lock.json +++ b/src/DodoSSH.Client.Sync/packages.lock.json @@ -252,20 +252,6 @@ "SQLitePCLRaw.core": "2.1.12" } } - }, - "net10.0/android-arm64": { - "libsodium": { - "type": "CentralTransitive", - "requested": "[1.0.22, )", - "resolved": "1.0.22", - "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" - }, - "SQLitePCLRaw.lib.e_sqlite3": { - "type": "CentralTransitive", - "requested": "[2.1.12, )", - "resolved": "2.1.12", - "contentHash": "fWi8Dbknuhgg72fWinIdjXVaqO1hHL4YBBwVLnr7e1c9TAZwJ0QE38j9syW1hwx6HaqEVTwI+O07WPdZn8Rp0w==" - } } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.Terminal/packages.lock.json b/src/DodoSSH.Client.Terminal/packages.lock.json index e1712a8..6e0493f 100644 --- a/src/DodoSSH.Client.Terminal/packages.lock.json +++ b/src/DodoSSH.Client.Terminal/packages.lock.json @@ -65,14 +65,6 @@ "Microsoft.Extensions.Logging.Abstractions": "8.0.3" } } - }, - "net10.0/android-arm64": { - "libsodium": { - "type": "CentralTransitive", - "requested": "[1.0.22, )", - "resolved": "1.0.22", - "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" - } } } } \ No newline at end of file diff --git a/src/DodoSSH.Client.Transfer/packages.lock.json b/src/DodoSSH.Client.Transfer/packages.lock.json index e1712a8..6e0493f 100644 --- a/src/DodoSSH.Client.Transfer/packages.lock.json +++ b/src/DodoSSH.Client.Transfer/packages.lock.json @@ -65,14 +65,6 @@ "Microsoft.Extensions.Logging.Abstractions": "8.0.3" } } - }, - "net10.0/android-arm64": { - "libsodium": { - "type": "CentralTransitive", - "requested": "[1.0.22, )", - "resolved": "1.0.22", - "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" - } } } } \ No newline at end of file diff --git a/src/DodoSSH.Contracts/packages.lock.json b/src/DodoSSH.Contracts/packages.lock.json index 395937b..a5a3876 100644 --- a/src/DodoSSH.Contracts/packages.lock.json +++ b/src/DodoSSH.Contracts/packages.lock.json @@ -26,7 +26,6 @@ "resolved": "10.0.10", "contentHash": "f5VCIE7AJpd5YvzNTeMGVzQIgyE9tX+AreTYwQF+REbu+DZo/2Ae+jNSwhPEYrVz6RRkd7y8ubXjk6Nn6Ka+Cg==" } - }, - "net10.0/android-arm64": {} + } } } \ No newline at end of file diff --git a/src/DodoSSH.Crypto/packages.lock.json b/src/DodoSSH.Crypto/packages.lock.json index 2f41cfd..52bb4f7 100644 --- a/src/DodoSSH.Crypto/packages.lock.json +++ b/src/DodoSSH.Crypto/packages.lock.json @@ -35,14 +35,6 @@ "resolved": "1.0.22", "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" } - }, - "net10.0/android-arm64": { - "libsodium": { - "type": "CentralTransitive", - "requested": "[1.0.22, )", - "resolved": "1.0.22", - "contentHash": "KPD9SloJFclrsjnhABu7dzWrcyYkwPbvx5l1gRSPAX/0n+OBtSiVCKtGFv4n+ecWUHU0tCG9LSSwoZZx673zBQ==" - } } } } \ No newline at end of file