about summary refs log tree commit diff
path: root/nixpkgs/pkgs/servers/web-apps
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/servers/web-apps')
-rw-r--r--nixpkgs/pkgs/servers/web-apps/5etools/default.nix20
-rw-r--r--nixpkgs/pkgs/servers/web-apps/anuko-time-tracker/default.nix42
-rw-r--r--nixpkgs/pkgs/servers/web-apps/bookstack/composer-env.nix244
-rw-r--r--nixpkgs/pkgs/servers/web-apps/bookstack/composition.nix15
-rw-r--r--nixpkgs/pkgs/servers/web-apps/bookstack/default.nix39
-rw-r--r--nixpkgs/pkgs/servers/web-apps/bookstack/php-packages.nix1118
-rwxr-xr-xnixpkgs/pkgs/servers/web-apps/bookstack/update.sh50
-rw-r--r--nixpkgs/pkgs/servers/web-apps/changedetection-io/default.nix85
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/action_mailer_ca_cert.patch12
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/admin_create.patch48
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/asserts_patch-package_from_path.patch13
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/assets_esbuild_from_path.patch13
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/assets_rake_command.patch13
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/auto_generated_path.patch13
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/default.nix414
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/how_to_update.md24
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/mail_receiver/default.nix39
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/nixos_defaults.patch13
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/notification_email.patch18
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugin_gem_api_version.patch13
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/README4
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/all-plugins.nix27
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-assign/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-bbcode-color/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/Gemfile6
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/Gemfile.lock25
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/default.nix18
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/gemset.nix66
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-canned-replies/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-chat-integration/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-checklist/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-data-explorer/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-docs/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/Gemfile7
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/Gemfile.lock27
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/default.nix19
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/gemset.nix76
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/Gemfile9
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/Gemfile.lock28
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/default.nix18
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/gemset.nix74
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-math/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/Gemfile10
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/Gemfile.lock26
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/default.nix18
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/gemset.nix64
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/Gemfile7
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/Gemfile.lock37
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/default.nix18
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/gemset.nix127
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/Gemfile7
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/Gemfile.lock37
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/default.nix19
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/gemset.nix127
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/Gemfile7
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/Gemfile.lock16
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/default.nix26
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/gemset.nix23
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/no-git-version.patch34
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/prometheus_exporter_version1
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/spec-import-fix-abi-version.patch20
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-reactions/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-saved-searches/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-solved/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-spoiler-alert/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-voting/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-yearly-review/default.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/Gemfile278
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/Gemfile.lock651
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/gemset.nix2560
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/unicorn_logging_and_timeout.patch25
-rwxr-xr-xnixpkgs/pkgs/servers/web-apps/discourse/update.py441
-rw-r--r--nixpkgs/pkgs/servers/web-apps/discourse/use_mv_instead_of_rename.patch22
-rw-r--r--nixpkgs/pkgs/servers/web-apps/dokuwiki/default.nix91
-rw-r--r--nixpkgs/pkgs/servers/web-apps/dolibarr/default.nix41
-rw-r--r--nixpkgs/pkgs/servers/web-apps/engelsystem/default.nix53
-rw-r--r--nixpkgs/pkgs/servers/web-apps/ethercalc/default.nix27
-rwxr-xr-xnixpkgs/pkgs/servers/web-apps/ethercalc/generate.sh16
-rw-r--r--nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages-generated.nix2053
-rw-r--r--nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages.json3
-rw-r--r--nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages.nix17
-rw-r--r--nixpkgs/pkgs/servers/web-apps/fileshelter/default.nix33
-rw-r--r--nixpkgs/pkgs/servers/web-apps/freshrss/default.nix45
-rw-r--r--nixpkgs/pkgs/servers/web-apps/galene/default.nix34
-rw-r--r--nixpkgs/pkgs/servers/web-apps/healthchecks/default.nix96
-rw-r--r--nixpkgs/pkgs/servers/web-apps/hedgedoc/default.nix117
-rw-r--r--nixpkgs/pkgs/servers/web-apps/invoiceplane/default.nix32
-rw-r--r--nixpkgs/pkgs/servers/web-apps/jirafeau/default.nix33
-rw-r--r--nixpkgs/pkgs/servers/web-apps/jitsi-meet/default.nix38
-rwxr-xr-xnixpkgs/pkgs/servers/web-apps/jitsi-meet/update.sh12
-rw-r--r--nixpkgs/pkgs/servers/web-apps/kasmweb/default.nix36
-rw-r--r--nixpkgs/pkgs/servers/web-apps/kavita/change-webroot.diff39
-rw-r--r--nixpkgs/pkgs/servers/web-apps/kavita/default.nix78
-rw-r--r--nixpkgs/pkgs/servers/web-apps/kavita/nuget-deps.nix420
-rw-r--r--nixpkgs/pkgs/servers/web-apps/lemmy/package.json149
-rw-r--r--nixpkgs/pkgs/servers/web-apps/lemmy/pin.json8
-rw-r--r--nixpkgs/pkgs/servers/web-apps/lemmy/server.nix64
-rw-r--r--nixpkgs/pkgs/servers/web-apps/lemmy/ui.nix98
-rwxr-xr-xnixpkgs/pkgs/servers/web-apps/lemmy/update.py163
-rw-r--r--nixpkgs/pkgs/servers/web-apps/linx-server/default.nix33
-rw-r--r--nixpkgs/pkgs/servers/web-apps/linx-server/test.patch74
-rw-r--r--nixpkgs/pkgs/servers/web-apps/livebook/default.nix42
-rw-r--r--nixpkgs/pkgs/servers/web-apps/matomo/bootstrap.php6
-rw-r--r--nixpkgs/pkgs/servers/web-apps/matomo/change-path-geoip2-4.x.patch10
-rw-r--r--nixpkgs/pkgs/servers/web-apps/matomo/change-path-geoip2-5.x.patch10
-rw-r--r--nixpkgs/pkgs/servers/web-apps/matomo/default.nix125
-rw-r--r--nixpkgs/pkgs/servers/web-apps/matomo/make-localhost-default-database-host.patch13
-rw-r--r--nixpkgs/pkgs/servers/web-apps/mediawiki/default.nix39
-rw-r--r--nixpkgs/pkgs/servers/web-apps/meme-bingo-web/default.nix35
-rw-r--r--nixpkgs/pkgs/servers/web-apps/monica/default.nix39
-rw-r--r--nixpkgs/pkgs/servers/web-apps/moodle/default.nix71
-rw-r--r--nixpkgs/pkgs/servers/web-apps/moodle/moodle-utils.nix33
-rw-r--r--nixpkgs/pkgs/servers/web-apps/morty/default.nix29
-rw-r--r--nixpkgs/pkgs/servers/web-apps/netbox/config.patch50
-rw-r--r--nixpkgs/pkgs/servers/web-apps/netbox/default.nix38
-rw-r--r--nixpkgs/pkgs/servers/web-apps/netbox/generic.nix112
-rw-r--r--nixpkgs/pkgs/servers/web-apps/nifi/default.nix46
-rw-r--r--nixpkgs/pkgs/servers/web-apps/outline/default.nix84
-rw-r--r--nixpkgs/pkgs/servers/web-apps/peering-manager/default.nix84
-rw-r--r--nixpkgs/pkgs/servers/web-apps/pgpkeyserver-lite/default.nix25
-rw-r--r--nixpkgs/pkgs/servers/web-apps/phylactery/default.nix32
-rw-r--r--nixpkgs/pkgs/servers/web-apps/phylactery/go.mod3
-rw-r--r--nixpkgs/pkgs/servers/web-apps/pict-rs/0.3.nix54
-rw-r--r--nixpkgs/pkgs/servers/web-apps/pict-rs/Cargo-0.3.lock3105
-rw-r--r--nixpkgs/pkgs/servers/web-apps/pict-rs/default.nix50
-rw-r--r--nixpkgs/pkgs/servers/web-apps/pixelfed/default.nix49
-rw-r--r--nixpkgs/pkgs/servers/web-apps/plausible/default.nix95
-rwxr-xr-xnixpkgs/pkgs/servers/web-apps/plausible/update.sh62
-rw-r--r--nixpkgs/pkgs/servers/web-apps/rss-bridge/default.nix30
-rw-r--r--nixpkgs/pkgs/servers/web-apps/rss-bridge/paths.patch38
-rw-r--r--nixpkgs/pkgs/servers/web-apps/selfoss/default.nix36
-rw-r--r--nixpkgs/pkgs/servers/web-apps/shaarli/default.nix61
-rw-r--r--nixpkgs/pkgs/servers/web-apps/shiori/default.nix29
-rw-r--r--nixpkgs/pkgs/servers/web-apps/slskd/default.nix60
-rw-r--r--nixpkgs/pkgs/servers/web-apps/slskd/deps.nix337
-rw-r--r--nixpkgs/pkgs/servers/web-apps/sogo/default.nix83
-rw-r--r--nixpkgs/pkgs/servers/web-apps/sogo/enable-activesync.patch21
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wallabag/default.nix57
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wallabag/wallabag-data.patch26
-rw-r--r--nixpkgs/pkgs/servers/web-apps/whitebophir/default.nix49
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wiki-js/default.nix35
-rwxr-xr-xnixpkgs/pkgs/servers/web-apps/wiki-js/update.sh13
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/default.nix11
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/generic.nix49
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/packages/README.md46
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/packages/default.nix95
-rwxr-xr-xnixpkgs/pkgs/servers/web-apps/wordpress/packages/generate.sh23
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/packages/languages.json20
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/packages/plugins.json218
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/packages/themes.json32
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/packages/thirdparty.nix25
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-languages.json5
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-plugins.json38
-rw-r--r--nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-themes.json7
154 files changed, 17177 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/servers/web-apps/5etools/default.nix b/nixpkgs/pkgs/servers/web-apps/5etools/default.nix
new file mode 100644
index 000000000000..856384aa173f
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/5etools/default.nix
@@ -0,0 +1,20 @@
+{ fetchFromGitHub, lib }:
+
+fetchFromGitHub rec {
+  pname = "5etools";
+  version = "1.175.2";
+
+  owner = "5etools-mirror-1";
+  repo = "5etools-mirror-1.github.io";
+  rev = "v${version}";
+  hash = "sha256-0+QjtcmKsfcSehvn4DChBhSVooy9wlqaSCgeAFgeL+w=";
+
+  meta = with lib; {
+    description = "A suite of browser-based tools for players and DMs of D&D 5e";
+    homepage = "https://5e.tools";
+    changelog = "https://github.com/5etools-mirror-1/5etools-mirror-1.github.io/releases/tag/v${version}";
+    license = [ licenses.mit ];
+    maintainers = with maintainers; [ urandom ];
+    hydraPlatforms = []; # src tarball is 4.7G, unpackeed 4.8G, exceeds hydras output limit
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/anuko-time-tracker/default.nix b/nixpkgs/pkgs/servers/web-apps/anuko-time-tracker/default.nix
new file mode 100644
index 000000000000..583f2db81938
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/anuko-time-tracker/default.nix
@@ -0,0 +1,42 @@
+{ lib
+, stdenvNoCC
+, fetchFromGitHub
+, nixosTests
+, php
+}:
+
+stdenvNoCC.mkDerivation rec {
+  pname = "anuko-time-tracker";
+  version = "1.22.19.5806";
+
+  # Project commits directly into master and has no release schedule.
+  # Fortunately the current version is defined in the 'APP_VERSION' constant in
+  # /initialize.php so we use its value and set the rev to the commit sha of when the
+  # constant was last updated.
+  src = fetchFromGitHub {
+    owner = "anuko";
+    repo = "timetracker";
+    rev = "43a19fcb51a21f6e3169084ac81308a6ef751e63";
+    hash = "sha256-ZRF9FFbntYY01JflCXkYZyXfyu/x7LNdyOB94UkVFR0=";
+  };
+
+  # There's nothing to build.
+  dontBuild = true;
+
+  installPhase = ''
+    mkdir $out/
+    cp -R ./* $out
+  '';
+
+  passthru.tests = {
+    inherit (nixosTests) anuko-time-tracker;
+  };
+
+  meta = {
+    description = "Simple, easy to use, open source time tracking system";
+    license = lib.licenses.sspl;
+    homepage = "https://github.com/anuko/timetracker/";
+    platforms = php.meta.platforms;
+    maintainers = with lib.maintainers; [ michaelshmitty ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/bookstack/composer-env.nix b/nixpkgs/pkgs/servers/web-apps/bookstack/composer-env.nix
new file mode 100644
index 000000000000..71714b764008
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/bookstack/composer-env.nix
@@ -0,0 +1,244 @@
+# This file originates from composer2nix
+
+{ stdenv, lib, writeTextFile, fetchurl, php, unzip, phpPackages }:
+
+let
+  inherit (phpPackages) composer;
+
+  filterSrc = src:
+    builtins.filterSource (path: type: type != "directory" || (baseNameOf path != ".git" && baseNameOf path != ".git" && baseNameOf path != ".svn")) src;
+
+  buildZipPackage = { name, src }:
+    stdenv.mkDerivation {
+      inherit name src;
+      nativeBuildInputs = [ unzip ];
+      buildCommand = ''
+        shopt -s dotglob
+        unzip $src
+        baseDir=$(find . -type d -mindepth 1 -maxdepth 1)
+        cd $baseDir
+        mkdir -p $out
+        mv * $out
+      '';
+    };
+
+  buildPackage =
+    { name
+    , src
+    , packages ? {}
+    , devPackages ? {}
+    , buildInputs ? []
+    , symlinkDependencies ? false
+    , executable ? false
+    , removeComposerArtifacts ? false
+    , postInstall ? ""
+    , noDev ? false
+    , composerExtraArgs ? ""
+    , unpackPhase ? "true"
+    , buildPhase ? "true"
+    , ...}@args:
+
+    let
+      reconstructInstalled = writeTextFile {
+        name = "reconstructinstalled.php";
+        executable = true;
+        text = ''
+          #! ${php}/bin/php
+          <?php
+          if(file_exists($argv[1]))
+          {
+              $composerLockStr = file_get_contents($argv[1]);
+
+              if($composerLockStr === false)
+              {
+                  fwrite(STDERR, "Cannot open composer.lock contents\n");
+                  exit(1);
+              }
+              else
+              {
+                  $config = json_decode($composerLockStr, true);
+
+                  if(array_key_exists("packages", $config))
+                      $allPackages = $config["packages"];
+                  else
+                      $allPackages = array();
+
+                  ${lib.optionalString (!noDev) ''
+                    if(array_key_exists("packages-dev", $config))
+                        $allPackages = array_merge($allPackages, $config["packages-dev"]);
+                  ''}
+
+                  $packagesStr = json_encode($allPackages, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
+                  print($packagesStr);
+              }
+          }
+          else
+              print("[]");
+          ?>
+        '';
+      };
+
+      constructBin = writeTextFile {
+        name = "constructbin.php";
+        executable = true;
+        text = ''
+          #! ${php}/bin/php
+          <?php
+          $composerJSONStr = file_get_contents($argv[1]);
+
+          if($composerJSONStr === false)
+          {
+              fwrite(STDERR, "Cannot open composer.json contents\n");
+              exit(1);
+          }
+          else
+          {
+              $config = json_decode($composerJSONStr, true);
+
+              if(array_key_exists("bin-dir", $config))
+                  $binDir = $config["bin-dir"];
+              else
+                  $binDir = "bin";
+
+              if(array_key_exists("bin", $config))
+              {
+                  if(!file_exists("vendor/".$binDir))
+                      mkdir("vendor/".$binDir);
+
+                  foreach($config["bin"] as $bin)
+                      symlink("../../".$bin, "vendor/".$binDir."/".basename($bin));
+              }
+          }
+          ?>
+        '';
+      };
+
+      bundleDependencies = dependencies:
+        lib.concatMapStrings (dependencyName:
+          let
+            dependency = dependencies.${dependencyName};
+          in
+          ''
+            ${if dependency.targetDir == "" then ''
+              vendorDir="$(dirname ${dependencyName})"
+              mkdir -p "$vendorDir"
+              ${if symlinkDependencies then
+                ''ln -s "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
+                else
+                ''cp -av "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
+              }
+            '' else ''
+              namespaceDir="${dependencyName}/$(dirname "${dependency.targetDir}")"
+              mkdir -p "$namespaceDir"
+              ${if symlinkDependencies then
+                ''ln -s "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
+              else
+                ''cp -av "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
+              }
+            ''}
+          '') (builtins.attrNames dependencies);
+
+      extraArgs = removeAttrs args [ "packages" "devPackages" "buildInputs" ];
+    in
+    stdenv.mkDerivation ({
+      buildInputs = [ php composer ] ++ buildInputs;
+
+      inherit unpackPhase buildPhase;
+
+      installPhase = ''
+        ${if executable then ''
+          mkdir -p $out/share/php
+          cp -av $src $out/share/php/$name
+          chmod -R u+w $out/share/php/$name
+          cd $out/share/php/$name
+        '' else ''
+          cp -av $src $out
+          chmod -R u+w $out
+          cd $out
+        ''}
+
+        # Remove unwanted files
+        rm -f *.nix
+
+        export HOME=$TMPDIR
+
+        # Remove the provided vendor folder if it exists
+        rm -Rf vendor
+
+        # If there is no composer.lock file, compose a dummy file.
+        # Otherwise, composer attempts to download the package.json file from
+        # the registry which we do not want.
+        if [ ! -f composer.lock ]
+        then
+            cat > composer.lock <<EOF
+        {
+            "packages": []
+        }
+        EOF
+        fi
+
+        # Reconstruct the installed.json file from the lock file
+        mkdir -p vendor/composer
+        ${php}/bin/php ${reconstructInstalled} composer.lock > vendor/composer/installed.json
+
+        # Copy or symlink the provided dependencies
+        cd vendor
+        ${bundleDependencies packages}
+        ${lib.optionalString (!noDev) (bundleDependencies devPackages)}
+        cd ..
+
+        # Reconstruct autoload scripts
+        # We use the optimize feature because Nix packages cannot change after they have been built
+        # Using the dynamic loader for a Nix package is useless since there is nothing to dynamically reload.
+        composer dump-autoload --optimize ${lib.optionalString noDev "--no-dev"} ${composerExtraArgs}
+
+        # Run the install step as a validation to confirm that everything works out as expected
+        composer install --optimize-autoloader ${lib.optionalString noDev "--no-dev"} ${composerExtraArgs}
+
+        ${lib.optionalString executable ''
+          # Reconstruct the bin/ folder if we deploy an executable project
+          ${php}/bin/php ${constructBin} composer.json
+          ln -s $(pwd)/vendor/bin $out/bin
+        ''}
+
+        ${lib.optionalString (!symlinkDependencies) ''
+          # Patch the shebangs if possible
+          if [ -d $(pwd)/vendor/bin ]
+          then
+              # Look for all executables in bin/
+              for i in $(pwd)/vendor/bin/*
+              do
+                  # Look for their location
+                  realFile=$(readlink -f "$i")
+
+                  # Restore write permissions
+                  chmod u+wx "$(dirname "$realFile")"
+                  chmod u+w "$realFile"
+
+                  # Patch shebang
+                  sed -e "s|#!/usr/bin/php|#!${php}/bin/php|" \
+                      -e "s|#!/usr/bin/env php|#!${php}/bin/php|" \
+                      "$realFile" > tmp
+                  mv tmp "$realFile"
+                  chmod u+x "$realFile"
+              done
+          fi
+        ''}
+
+        if [ "$removeComposerArtifacts" = "1" ]
+        then
+            # Remove composer stuff
+            rm -f composer.json composer.lock
+        fi
+
+        # Execute post install hook
+        runHook postInstall
+    '';
+  } // extraArgs);
+in
+{
+  inherit filterSrc;
+  composer = lib.makeOverridable composer;
+  buildZipPackage = lib.makeOverridable buildZipPackage;
+  buildPackage = lib.makeOverridable buildPackage;
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/bookstack/composition.nix b/nixpkgs/pkgs/servers/web-apps/bookstack/composition.nix
new file mode 100644
index 000000000000..d8df4b81fa3e
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/bookstack/composition.nix
@@ -0,0 +1,15 @@
+{pkgs ? import <nixpkgs> {
+    inherit system;
+  }, system ? builtins.currentSystem, noDev ? false, php ? pkgs.php, phpPackages ? pkgs.phpPackages}:
+
+let
+  composerEnv = import ./composer-env.nix {
+    inherit (pkgs) stdenv lib writeTextFile fetchurl unzip;
+    inherit php phpPackages;
+  };
+in
+import ./php-packages.nix {
+  inherit composerEnv noDev;
+  inherit (pkgs) fetchurl fetchgit fetchhg fetchsvn;
+}
+
diff --git a/nixpkgs/pkgs/servers/web-apps/bookstack/default.nix b/nixpkgs/pkgs/servers/web-apps/bookstack/default.nix
new file mode 100644
index 000000000000..227d4185baf8
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/bookstack/default.nix
@@ -0,0 +1,39 @@
+{ pkgs, stdenv, lib, fetchFromGitHub, dataDir ? "/var/lib/bookstack" }:
+
+let
+  package = (import ./composition.nix {
+    inherit pkgs;
+    inherit (stdenv.hostPlatform) system;
+    noDev = true; # Disable development dependencies
+  }).overrideAttrs (attrs : {
+    installPhase = attrs.installPhase + ''
+      rm -R $out/storage $out/public/uploads
+      ln -s ${dataDir}/.env $out/.env
+      ln -s ${dataDir}/storage $out/storage
+      ln -s ${dataDir}/public/uploads $out/public/uploads
+    '';
+  });
+
+in package.override rec {
+  pname = "bookstack";
+  version = "24.02.2";
+
+  src = fetchFromGitHub {
+    owner = "bookstackapp";
+    repo = pname;
+    rev = "v${version}";
+    sha256 = "1b4166vd3ribs69ad5ljp71im0fh0n0m5c5l04i3l44a5bw25b2h";
+  };
+
+  meta = with lib; {
+    description = "A platform to create documentation/wiki content built with PHP & Laravel";
+    longDescription = ''
+      A platform for storing and organising information and documentation.
+      Details for BookStack can be found on the official website at https://www.bookstackapp.com/.
+    '';
+    homepage = "https://www.bookstackapp.com/";
+    license = licenses.mit;
+    maintainers = with maintainers; [ ymarkus ];
+    platforms = platforms.linux;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/bookstack/php-packages.nix b/nixpkgs/pkgs/servers/web-apps/bookstack/php-packages.nix
new file mode 100644
index 000000000000..7c343011726c
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/bookstack/php-packages.nix
@@ -0,0 +1,1118 @@
+{composerEnv, fetchurl, fetchgit ? null, fetchhg ? null, fetchsvn ? null, noDev ? false}:
+
+let
+  packages = {
+    "aws/aws-crt-php" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "aws-aws-crt-php-eb0c6e4e142224a10b08f49ebf87f32611d162b2";
+        src = fetchurl {
+          url = "https://api.github.com/repos/awslabs/aws-crt-php/zipball/eb0c6e4e142224a10b08f49ebf87f32611d162b2";
+          sha256 = "10fnazz3gv51i6dngrc6hbcmzwrvl6mmd2z44rrdbzz3ry8v3vc9";
+        };
+      };
+    };
+    "aws/aws-sdk-php" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "aws-aws-sdk-php-957ccef631684d612d01ced2fa3b0506f2ec78c3";
+        src = fetchurl {
+          url = "https://api.github.com/repos/aws/aws-sdk-php/zipball/957ccef631684d612d01ced2fa3b0506f2ec78c3";
+          sha256 = "1chckiccr061c063wwf502d545wji4p5g6ak6z6dl36jjkrip7v4";
+        };
+      };
+    };
+    "bacon/bacon-qr-code" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "bacon-bacon-qr-code-8674e51bb65af933a5ffaf1c308a660387c35c22";
+        src = fetchurl {
+          url = "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22";
+          sha256 = "0hb0w6m5rwzghw2im3yqn6ly2kvb3jgrv8jwra1lwd0ik6ckrngl";
+        };
+      };
+    };
+    "barryvdh/laravel-dompdf" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "barryvdh-laravel-dompdf-9843d2be423670fb434f4c978b3c0f4dd92c87a6";
+        src = fetchurl {
+          url = "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/9843d2be423670fb434f4c978b3c0f4dd92c87a6";
+          sha256 = "1b7j7rnba50ibsnjzxz3bcnpcii51qrin5p0ivi0bzm57xhvns9s";
+        };
+      };
+    };
+    "barryvdh/laravel-snappy" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "barryvdh-laravel-snappy-940eec2d99b89cbc9bea2f493cf068382962a485";
+        src = fetchurl {
+          url = "https://api.github.com/repos/barryvdh/laravel-snappy/zipball/940eec2d99b89cbc9bea2f493cf068382962a485";
+          sha256 = "0i168sq1sah83xw3xfrilnpja789q79zvhjfgfcszd10g7y444gc";
+        };
+      };
+    };
+    "brick/math" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "brick-math-0ad82ce168c82ba30d1c01ec86116ab52f589478";
+        src = fetchurl {
+          url = "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478";
+          sha256 = "04kqy1hqvp4634njjjmhrc2g828d69sk6q3c55bpqnnmsqf154yb";
+        };
+      };
+    };
+    "carbonphp/carbon-doctrine-types" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "carbonphp-carbon-doctrine-types-99f76ffa36cce3b70a4a6abce41dba15ca2e84cb";
+        src = fetchurl {
+          url = "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb";
+          sha256 = "0vkhwbprqlcg4awdknaycbfydb4spk7vd1v0nxbq06zx22dmphaz";
+        };
+      };
+    };
+    "dasprid/enum" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "dasprid-enum-6faf451159fb8ba4126b925ed2d78acfce0dc016";
+        src = fetchurl {
+          url = "https://api.github.com/repos/DASPRiD/Enum/zipball/6faf451159fb8ba4126b925ed2d78acfce0dc016";
+          sha256 = "1c3c7zdmpd5j1pw9am0k3mj8n17vy6xjhsh2qa7c0azz0f21jk4j";
+        };
+      };
+    };
+    "dflydev/dot-access-data" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "dflydev-dot-access-data-f41715465d65213d644d3141a6a93081be5d3549";
+        src = fetchurl {
+          url = "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549";
+          sha256 = "1vgbjrq8qh06r26y5nlxfin4989r3h7dib1jifb2l3cjdn1r5bmj";
+        };
+      };
+    };
+    "doctrine/cache" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "doctrine-cache-1ca8f21980e770095a31456042471a57bc4c68fb";
+        src = fetchurl {
+          url = "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb";
+          sha256 = "1p8ia9g3mqz71bv4x8q1ng1fgcidmyksbsli1fjbialpgjk9k1ss";
+        };
+      };
+    };
+    "doctrine/dbal" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "doctrine-dbal-a19a1d05ca211f41089dffcc387733a6875196cb";
+        src = fetchurl {
+          url = "https://api.github.com/repos/doctrine/dbal/zipball/a19a1d05ca211f41089dffcc387733a6875196cb";
+          sha256 = "11lcmw8pmgfp7wmn4miainyl2c060s4igq4g94azxl1v5bqaypis";
+        };
+      };
+    };
+    "doctrine/deprecations" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "doctrine-deprecations-dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab";
+        src = fetchurl {
+          url = "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab";
+          sha256 = "1qydhnf94wgjlrgzydjcz31rr5f87pg3vlkkd0gynggw1ycgkkcg";
+        };
+      };
+    };
+    "doctrine/event-manager" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "doctrine-event-manager-95aa4cb529f1e96576f3fda9f5705ada4056a520";
+        src = fetchurl {
+          url = "https://api.github.com/repos/doctrine/event-manager/zipball/95aa4cb529f1e96576f3fda9f5705ada4056a520";
+          sha256 = "0xi2s28jmmvrndg1yd0r5s10d9a0q6j2dxdbazvcbws9waf0yrvj";
+        };
+      };
+    };
+    "doctrine/inflector" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "doctrine-inflector-5817d0659c5b50c9b950feb9af7b9668e2c436bc";
+        src = fetchurl {
+          url = "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc";
+          sha256 = "0yj0f6w0v35d0xdhy4bf7hsjrkjjxsglc879rdciybsk6vz70g96";
+        };
+      };
+    };
+    "doctrine/lexer" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "doctrine-lexer-861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6";
+        src = fetchurl {
+          url = "https://api.github.com/repos/doctrine/lexer/zipball/861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6";
+          sha256 = "0q25i1d6nqkrj4yc35my6b51kn2nksddhddm13vkc7ilkkn20pg7";
+        };
+      };
+    };
+    "dompdf/dompdf" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "dompdf-dompdf-093f2d9739cec57428e39ddadedfd4f3ae862c0f";
+        src = fetchurl {
+          url = "https://api.github.com/repos/dompdf/dompdf/zipball/093f2d9739cec57428e39ddadedfd4f3ae862c0f";
+          sha256 = "0852xp3qfg40byhv7z4bma9bpiyrc3yral3p9xhk8g62jjddvayn";
+        };
+      };
+    };
+    "dragonmantank/cron-expression" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "dragonmantank-cron-expression-adfb1f505deb6384dc8b39804c5065dd3c8c8c0a";
+        src = fetchurl {
+          url = "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a";
+          sha256 = "1gw2bnsh8ca5plfpyyyz1idnx7zxssg6fbwl7niszck773zrm5ca";
+        };
+      };
+    };
+    "egulias/email-validator" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "egulias-email-validator-e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7";
+        src = fetchurl {
+          url = "https://api.github.com/repos/egulias/EmailValidator/zipball/e5997fa97e8790cdae03a9cbd5e78e45e3c7bda7";
+          sha256 = "16s7k5ck8bzk83xfy46fikjyj4jywalriqba8jvd5ngd177s2mw5";
+        };
+      };
+    };
+    "fruitcake/php-cors" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "fruitcake-php-cors-3d158f36e7875e2f040f37bc0573956240a5a38b";
+        src = fetchurl {
+          url = "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b";
+          sha256 = "1pdq0dxrmh4yj48y9azrld10qmz1w3vbb9q81r85fvgl62l2kiww";
+        };
+      };
+    };
+    "graham-campbell/result-type" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "graham-campbell-result-type-fbd48bce38f73f8a4ec8583362e732e4095e5862";
+        src = fetchurl {
+          url = "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862";
+          sha256 = "1mzahy4df8d45qm716crs45rp5j7k31r0jhkmbrrvqsvapnmj9ip";
+        };
+      };
+    };
+    "guzzlehttp/guzzle" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "guzzlehttp-guzzle-41042bc7ab002487b876a0683fc8dce04ddce104";
+        src = fetchurl {
+          url = "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104";
+          sha256 = "0awhhka285kk0apv92n0a0yfbihi2ddnx3qr1c7s97asgxfnwxsv";
+        };
+      };
+    };
+    "guzzlehttp/promises" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "guzzlehttp-promises-bbff78d96034045e58e13dedd6ad91b5d1253223";
+        src = fetchurl {
+          url = "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223";
+          sha256 = "1p0bry118c3lichkz8lag37ndvvhbd2nf0k9kzwi8gz1bzf9d45f";
+        };
+      };
+    };
+    "guzzlehttp/psr7" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "guzzlehttp-psr7-45b30f99ac27b5ca93cb4831afe16285f57b8221";
+        src = fetchurl {
+          url = "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221";
+          sha256 = "0k60pzfpxd6q1rhr9gbf53j0hm9wj5p5spkc0zfyia4b8f8pgmdm";
+        };
+      };
+    };
+    "guzzlehttp/uri-template" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "guzzlehttp-uri-template-ecea8feef63bd4fef1f037ecb288386999ecc11c";
+        src = fetchurl {
+          url = "https://api.github.com/repos/guzzle/uri-template/zipball/ecea8feef63bd4fef1f037ecb288386999ecc11c";
+          sha256 = "0r3cbb2pgsy4nawbylc0nbski2r9dkl335ay5m4i82yglspl9zz4";
+        };
+      };
+    };
+    "intervention/image" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "intervention-image-04be355f8d6734c826045d02a1079ad658322dad";
+        src = fetchurl {
+          url = "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad";
+          sha256 = "1cbg43hm2jgwb7gm1r9xcr4cpx8ng1zr93zx6shk9xhjlssnv0bx";
+        };
+      };
+    };
+    "knplabs/knp-snappy" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "knplabs-knp-snappy-3db13fe45d12a7bccb2b83f622e5a90f7e40b111";
+        src = fetchurl {
+          url = "https://api.github.com/repos/KnpLabs/snappy/zipball/3db13fe45d12a7bccb2b83f622e5a90f7e40b111";
+          sha256 = "1l4nln4cg01ywv9lzi5srnm7jq4q1v0210j9sshq34vx8slll9di";
+        };
+      };
+    };
+    "laravel/framework" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "laravel-framework-082345d76fc6a55b649572efe10b11b03e279d24";
+        src = fetchurl {
+          url = "https://api.github.com/repos/laravel/framework/zipball/082345d76fc6a55b649572efe10b11b03e279d24";
+          sha256 = "0gzpj0cgnqncxd4h196k5mvv169xzmy8c6bdwm5pkdy0f2hnb6lq";
+        };
+      };
+    };
+    "laravel/serializable-closure" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "laravel-serializable-closure-3dbf8a8e914634c48d389c1234552666b3d43754";
+        src = fetchurl {
+          url = "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754";
+          sha256 = "1vvayh1bzbw16xj8ash4flibkgn5afwn64nfwmjdi7lcr48cw65q";
+        };
+      };
+    };
+    "laravel/socialite" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "laravel-socialite-7dae1b072573809f32ab6dcf4aebb57c8b3e8acf";
+        src = fetchurl {
+          url = "https://api.github.com/repos/laravel/socialite/zipball/7dae1b072573809f32ab6dcf4aebb57c8b3e8acf";
+          sha256 = "1jd65mk5hww4iq6xkky1dkmz8c06czlb466s4svg4vf1xhb9dxqj";
+        };
+      };
+    };
+    "laravel/tinker" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "laravel-tinker-502e0fe3f0415d06d5db1f83a472f0f3b754bafe";
+        src = fetchurl {
+          url = "https://api.github.com/repos/laravel/tinker/zipball/502e0fe3f0415d06d5db1f83a472f0f3b754bafe";
+          sha256 = "13l5lm6xz9qad3nmld8sjr4bznh82z8s4kr8kkd8d8a1ai6jd0aq";
+        };
+      };
+    };
+    "league/commonmark" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "league-commonmark-91c24291965bd6d7c46c46a12ba7492f83b1cadf";
+        src = fetchurl {
+          url = "https://api.github.com/repos/thephpleague/commonmark/zipball/91c24291965bd6d7c46c46a12ba7492f83b1cadf";
+          sha256 = "1i7yqcp4hdzz1k6qga96jwp9qpw7dxlfr5miw48zyym60ndk9n02";
+        };
+      };
+    };
+    "league/config" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "league-config-754b3604fb2984c71f4af4a9cbe7b57f346ec1f3";
+        src = fetchurl {
+          url = "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3";
+          sha256 = "0yjb85cd0qa0mra995863dij2hmcwk9x124vs8lrwiylb0l3mn8s";
+        };
+      };
+    };
+    "league/flysystem" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "league-flysystem-b25a361508c407563b34fac6f64a8a17a8819675";
+        src = fetchurl {
+          url = "https://api.github.com/repos/thephpleague/flysystem/zipball/b25a361508c407563b34fac6f64a8a17a8819675";
+          sha256 = "07fd3nqvs9wnl7wwlii3aaalpdldgf6agk2l1ihl3w253qyg8ynn";
+        };
+      };
+    };
+    "league/flysystem-aws-s3-v3" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "league-flysystem-aws-s3-v3-809474e37b7fb1d1f8bcc0f8a98bc1cae99aa513";
+        src = fetchurl {
+          url = "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/809474e37b7fb1d1f8bcc0f8a98bc1cae99aa513";
+          sha256 = "0iv1n4y6w4pa2051wxvnkcap08jb86qgfx1hb6w8z5rngg67nz4d";
+        };
+      };
+    };
+    "league/flysystem-local" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "league-flysystem-local-b884d2bf9b53bb4804a56d2df4902bb51e253f00";
+        src = fetchurl {
+          url = "https://api.github.com/repos/thephpleague/flysystem-local/zipball/b884d2bf9b53bb4804a56d2df4902bb51e253f00";
+          sha256 = "1ggpc08rdaqk2wxkvklfi6l7nqzd6ch2dgf9icr1shfiv09l0mp6";
+        };
+      };
+    };
+    "league/html-to-markdown" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "league-html-to-markdown-0b4066eede55c48f38bcee4fb8f0aa85654390fd";
+        src = fetchurl {
+          url = "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/0b4066eede55c48f38bcee4fb8f0aa85654390fd";
+          sha256 = "0cd0sv99albdkrj4hmrbb76ji366dsl4jcpsr9gmrrpy3jxi2h7a";
+        };
+      };
+    };
+    "league/mime-type-detection" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "league-mime-type-detection-ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301";
+        src = fetchurl {
+          url = "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301";
+          sha256 = "1yvjnqb6wv6kxfs21qw31yqcb653dz2xw9g646y2g9via33fxvpd";
+        };
+      };
+    };
+    "league/oauth1-client" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "league-oauth1-client-d6365b901b5c287dd41f143033315e2f777e1167";
+        src = fetchurl {
+          url = "https://api.github.com/repos/thephpleague/oauth1-client/zipball/d6365b901b5c287dd41f143033315e2f777e1167";
+          sha256 = "0hkh8l7884g8ssja1biwfb59x0jj951lwk6kmiacjqvyvzs07qmx";
+        };
+      };
+    };
+    "league/oauth2-client" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "league-oauth2-client-160d6274b03562ebeb55ed18399281d8118b76c8";
+        src = fetchurl {
+          url = "https://api.github.com/repos/thephpleague/oauth2-client/zipball/160d6274b03562ebeb55ed18399281d8118b76c8";
+          sha256 = "1vyd8c64armlaf9zmpjx2gy0nvv4mhzy5qk9k26k75wa9ffh482s";
+        };
+      };
+    };
+    "masterminds/html5" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "masterminds-html5-f47dcf3c70c584de14f21143c55d9939631bc6cf";
+        src = fetchurl {
+          url = "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf";
+          sha256 = "1n2xiyxqmxk9g34wn1lg2yyivwg2ry8iqk8m7g2432gm97rmyb20";
+        };
+      };
+    };
+    "monolog/monolog" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "monolog-monolog-437cb3628f4cf6042cc10ae97fc2b8472e48ca1f";
+        src = fetchurl {
+          url = "https://api.github.com/repos/Seldaek/monolog/zipball/437cb3628f4cf6042cc10ae97fc2b8472e48ca1f";
+          sha256 = "02xaa057fj2bjf6g6zx80rb6ikcgn601ns50ml51b8yp48pjdla3";
+        };
+      };
+    };
+    "mtdowling/jmespath.php" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "mtdowling-jmespath.php-bbb69a935c2cbb0c03d7f481a238027430f6440b";
+        src = fetchurl {
+          url = "https://api.github.com/repos/jmespath/jmespath.php/zipball/bbb69a935c2cbb0c03d7f481a238027430f6440b";
+          sha256 = "1ksjdc2icgafkx16j05ir3vk1ryhgdr2l41wpfd6nhzzk42smiwb";
+        };
+      };
+    };
+    "nesbot/carbon" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "nesbot-carbon-0c6fd108360c562f6e4fd1dedb8233b423e91c83";
+        src = fetchurl {
+          url = "https://api.github.com/repos/briannesbitt/Carbon/zipball/0c6fd108360c562f6e4fd1dedb8233b423e91c83";
+          sha256 = "1qwdzf2jgppj2r8jpxxd1q08aycyvj17azy2ixlw4cnmwhcqzgnh";
+        };
+      };
+    };
+    "nette/schema" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "nette-schema-0462f0166e823aad657c9224d0f849ecac1ba10a";
+        src = fetchurl {
+          url = "https://api.github.com/repos/nette/schema/zipball/0462f0166e823aad657c9224d0f849ecac1ba10a";
+          sha256 = "0x2pz3mjnx78ndxm5532ld3kwzs9p43l4snk4vjbwnqiqgcpqwn7";
+        };
+      };
+    };
+    "nette/utils" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "nette-utils-d3ad0aa3b9f934602cb3e3902ebccf10be34d218";
+        src = fetchurl {
+          url = "https://api.github.com/repos/nette/utils/zipball/d3ad0aa3b9f934602cb3e3902ebccf10be34d218";
+          sha256 = "11df93i9xkwkfq33hqf2x562a36sibzpc6rkbblz2r10mna6qw6q";
+        };
+      };
+    };
+    "nikic/php-parser" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "nikic-php-parser-2218c2252c874a4624ab2f613d86ac32d227bc69";
+        src = fetchurl {
+          url = "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69";
+          sha256 = "1dkil9kcp1abwa4nhpmy8my6srj70994mjh7wnhyw8yy084nf11z";
+        };
+      };
+    };
+    "nunomaduro/termwind" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "nunomaduro-termwind-8ab0b32c8caa4a2e09700ea32925441385e4a5dc";
+        src = fetchurl {
+          url = "https://api.github.com/repos/nunomaduro/termwind/zipball/8ab0b32c8caa4a2e09700ea32925441385e4a5dc";
+          sha256 = "1g75vpq7014s5yd6bvj78b88ia31slkikdhjv8iprz987qm5dnl7";
+        };
+      };
+    };
+    "onelogin/php-saml" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "onelogin-php-saml-b22a57ebd13e838b90df5d3346090bc37056409d";
+        src = fetchurl {
+          url = "https://api.github.com/repos/onelogin/php-saml/zipball/b22a57ebd13e838b90df5d3346090bc37056409d";
+          sha256 = "1bi65bi04a26zmaz7ms0qyg6i86k4cd9g8qs7dp1pphpvflgz461";
+        };
+      };
+    };
+    "paragonie/constant_time_encoding" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "paragonie-constant_time_encoding-58c3f47f650c94ec05a151692652a868995d2938";
+        src = fetchurl {
+          url = "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/58c3f47f650c94ec05a151692652a868995d2938";
+          sha256 = "0i9km0lzvc7df9758fm1p3y0679pzvr5m9x3mrz0d2hxlppsm764";
+        };
+      };
+    };
+    "paragonie/random_compat" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "paragonie-random_compat-996434e5492cb4c3edcb9168db6fbb1359ef965a";
+        src = fetchurl {
+          url = "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a";
+          sha256 = "0ky7lal59dihf969r1k3pb96ql8zzdc5062jdbg69j6rj0scgkyx";
+        };
+      };
+    };
+    "phenx/php-font-lib" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "phenx-php-font-lib-a1681e9793040740a405ac5b189275059e2a9863";
+        src = fetchurl {
+          url = "https://api.github.com/repos/dompdf/php-font-lib/zipball/a1681e9793040740a405ac5b189275059e2a9863";
+          sha256 = "0xb28w943pg0xb5mmm2jd74vr14k2lwh40azpfv0p4ghfg16v3jp";
+        };
+      };
+    };
+    "phenx/php-svg-lib" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "phenx-php-svg-lib-732faa9fb4309221e2bd9b2fda5de44f947133aa";
+        src = fetchurl {
+          url = "https://api.github.com/repos/dompdf/php-svg-lib/zipball/732faa9fb4309221e2bd9b2fda5de44f947133aa";
+          sha256 = "0hjf562cm8mvb36c2s63bh5104j6m5c27lwd4pgj3lwmq6mpzns6";
+        };
+      };
+    };
+    "phpoption/phpoption" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "phpoption-phpoption-80735db690fe4fc5c76dfa7f9b770634285fa820";
+        src = fetchurl {
+          url = "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820";
+          sha256 = "1f9hzyjnam157lb7iw9r8f5cnjjsiqam9mnkpqmba73g1668xn9s";
+        };
+      };
+    };
+    "phpseclib/phpseclib" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "phpseclib-phpseclib-c2fb5136162d4be18fdd4da9980696f3aee96d7b";
+        src = fetchurl {
+          url = "https://api.github.com/repos/phpseclib/phpseclib/zipball/c2fb5136162d4be18fdd4da9980696f3aee96d7b";
+          sha256 = "1n13c34w27vkrjz87vq7dxzz1xi0vj7xzj5slibdm1wfpvbsbg2m";
+        };
+      };
+    };
+    "pragmarx/google2fa" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "pragmarx-google2fa-80c3d801b31fe165f8fe99ea085e0a37834e1be3";
+        src = fetchurl {
+          url = "https://api.github.com/repos/antonioribeiro/google2fa/zipball/80c3d801b31fe165f8fe99ea085e0a37834e1be3";
+          sha256 = "0qfjgkl02ifc0zicv3d5d6zs8mwpq68bg211jy3psgghnqpxyhlm";
+        };
+      };
+    };
+    "predis/predis" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "predis-predis-b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1";
+        src = fetchurl {
+          url = "https://api.github.com/repos/predis/predis/zipball/b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1";
+          sha256 = "0pylca7in1fm6vyrfdp12pqamp7y09cr5mc8hyr1m22r9f6m82l9";
+        };
+      };
+    };
+    "psr/cache" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "psr-cache-aa5030cfa5405eccfdcb1083ce040c2cb8d253bf";
+        src = fetchurl {
+          url = "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf";
+          sha256 = "07rnyjwb445sfj30v5ny3gfsgc1m7j7cyvwjgs2cm9slns1k1ml8";
+        };
+      };
+    };
+    "psr/clock" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "psr-clock-e41a24703d4560fd0acb709162f73b8adfc3aa0d";
+        src = fetchurl {
+          url = "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d";
+          sha256 = "0wz5b8hgkxn3jg88cb3901hj71axsj0fil6pwl413igghch6i8kj";
+        };
+      };
+    };
+    "psr/container" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "psr-container-c71ecc56dfe541dbd90c5360474fbc405f8d5963";
+        src = fetchurl {
+          url = "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963";
+          sha256 = "1mvan38yb65hwk68hl0p7jymwzr4zfnaxmwjbw7nj3rsknvga49i";
+        };
+      };
+    };
+    "psr/event-dispatcher" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "psr-event-dispatcher-dbefd12671e8a14ec7f180cab83036ed26714bb0";
+        src = fetchurl {
+          url = "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0";
+          sha256 = "05nicsd9lwl467bsv4sn44fjnnvqvzj1xqw2mmz9bac9zm66fsjd";
+        };
+      };
+    };
+    "psr/http-client" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "psr-http-client-bb5906edc1c324c9a05aa0873d40117941e5fa90";
+        src = fetchurl {
+          url = "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90";
+          sha256 = "1dfyjqj1bs2n2zddk8402v6rjq93fq26hwr0rjh53m11wy1wagsx";
+        };
+      };
+    };
+    "psr/http-factory" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "psr-http-factory-e616d01114759c4c489f93b099585439f795fe35";
+        src = fetchurl {
+          url = "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35";
+          sha256 = "1vzimn3h01lfz0jx0lh3cy9whr3kdh103m1fw07qric4pnnz5kx8";
+        };
+      };
+    };
+    "psr/http-message" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "psr-http-message-402d35bcb92c70c026d1a6a9883f06b2ead23d71";
+        src = fetchurl {
+          url = "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71";
+          sha256 = "13cnlzrh344n00sgkrp5cgbkr8dznd99c3jfnpl0wg1fdv1x4qfm";
+        };
+      };
+    };
+    "psr/log" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "psr-log-fe5ea303b0887d5caefd3d431c3e61ad47037001";
+        src = fetchurl {
+          url = "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001";
+          sha256 = "0a0rwg38vdkmal3nwsgx58z06qkfl85w2yvhbgwg45anr0b3bhmv";
+        };
+      };
+    };
+    "psr/simple-cache" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "psr-simple-cache-764e0b3939f5ca87cb904f570ef9be2d78a07865";
+        src = fetchurl {
+          url = "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865";
+          sha256 = "0hgcanvd9gqwkaaaq41lh8fsfdraxmp2n611lvqv69jwm1iy76g8";
+        };
+      };
+    };
+    "psy/psysh" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "psy-psysh-750bf031a48fd07c673dbe3f11f72362ea306d0d";
+        src = fetchurl {
+          url = "https://api.github.com/repos/bobthecow/psysh/zipball/750bf031a48fd07c673dbe3f11f72362ea306d0d";
+          sha256 = "0kcs6g31v6k760dwapdbx34vqliispf8dhwrjjgrv34ysfbwrgvc";
+        };
+      };
+    };
+    "ralouphie/getallheaders" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "ralouphie-getallheaders-120b605dfeb996808c31b6477290a714d356e822";
+        src = fetchurl {
+          url = "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822";
+          sha256 = "1bv7ndkkankrqlr2b4kw7qp3fl0dxi6bp26bnim6dnlhavd6a0gg";
+        };
+      };
+    };
+    "ramsey/collection" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "ramsey-collection-ad7475d1c9e70b190ecffc58f2d989416af339b4";
+        src = fetchurl {
+          url = "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4";
+          sha256 = "1a1wqdwdrbzkf2hias2kw9crr31265pn027vm69pr7alyq2qrzfw";
+        };
+      };
+    };
+    "ramsey/uuid" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "ramsey-uuid-5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e";
+        src = fetchurl {
+          url = "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e";
+          sha256 = "0gnpj6jsmwr5azxq8ymp0zpscgxcwld7ps2q9rbkbndr9f9cpkkg";
+        };
+      };
+    };
+    "robrichards/xmlseclibs" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "robrichards-xmlseclibs-f8f19e58f26cdb42c54b214ff8a820760292f8df";
+        src = fetchurl {
+          url = "https://api.github.com/repos/robrichards/xmlseclibs/zipball/f8f19e58f26cdb42c54b214ff8a820760292f8df";
+          sha256 = "01zlpm36rrdj310cfmiz2fnabszxd3fq80fa8x8j3f9ki7dvhh5y";
+        };
+      };
+    };
+    "sabberworm/php-css-parser" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "sabberworm-php-css-parser-4a3d572b0f8b28bb6fd016ae8bbfc445facef152";
+        src = fetchurl {
+          url = "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/4a3d572b0f8b28bb6fd016ae8bbfc445facef152";
+          sha256 = "1gs3q8j70ccwa2s3icf936xxik8h3qi5plkpvw4ygzkb9vkcicdv";
+        };
+      };
+    };
+    "socialiteproviders/discord" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "socialiteproviders-discord-c71c379acfdca5ba4aa65a3db5ae5222852a919c";
+        src = fetchurl {
+          url = "https://api.github.com/repos/SocialiteProviders/Discord/zipball/c71c379acfdca5ba4aa65a3db5ae5222852a919c";
+          sha256 = "0xly514yax8rlz91pp86s24apcam1cvjnphanjhdshd42hmpwr7w";
+        };
+      };
+    };
+    "socialiteproviders/gitlab" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "socialiteproviders-gitlab-a8f67d3b02c9ee8c70c25c6728417c0eddcbbb9d";
+        src = fetchurl {
+          url = "https://api.github.com/repos/SocialiteProviders/GitLab/zipball/a8f67d3b02c9ee8c70c25c6728417c0eddcbbb9d";
+          sha256 = "1blv2h69dmm0r0djz3h0l0cxkxmzd1fzgg13r3npxx7c80xjpw3a";
+        };
+      };
+    };
+    "socialiteproviders/manager" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "socialiteproviders-manager-a67f194f0f4c4c7616c549afc697b78df9658d44";
+        src = fetchurl {
+          url = "https://api.github.com/repos/SocialiteProviders/Manager/zipball/a67f194f0f4c4c7616c549afc697b78df9658d44";
+          sha256 = "0r5c6q7dm02hnk574br5mrm1z8amrxjxcbf4n94l02vq9din2c0m";
+        };
+      };
+    };
+    "socialiteproviders/microsoft-azure" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "socialiteproviders-microsoft-azure-7522b27cd8518706b50e03b40a396fb0a6891feb";
+        src = fetchurl {
+          url = "https://api.github.com/repos/SocialiteProviders/Microsoft-Azure/zipball/7522b27cd8518706b50e03b40a396fb0a6891feb";
+          sha256 = "0nlxyvcn3vc273rq9cp2yhm72mqfj31csnla5bqsaqdshzfk8pna";
+        };
+      };
+    };
+    "socialiteproviders/okta" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "socialiteproviders-okta-5e47cd7b4c19da94ecafbd91fa430e4151c09806";
+        src = fetchurl {
+          url = "https://api.github.com/repos/SocialiteProviders/Okta/zipball/5e47cd7b4c19da94ecafbd91fa430e4151c09806";
+          sha256 = "0padnyfg93avx33gq2acsss3kpclxsg43b9zywas1rd98d3md1di";
+        };
+      };
+    };
+    "socialiteproviders/twitch" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "socialiteproviders-twitch-7accf30ae7a3139b757b4ca8f34989c09a3dbee7";
+        src = fetchurl {
+          url = "https://api.github.com/repos/SocialiteProviders/Twitch/zipball/7accf30ae7a3139b757b4ca8f34989c09a3dbee7";
+          sha256 = "089i4fwxb32zmbxib0544jfs48wzjyp7bsqss2bf2xx89dsrx4ah";
+        };
+      };
+    };
+    "ssddanbrown/htmldiff" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "ssddanbrown-htmldiff-58f81857c02b50b199273edb4cc339876b5a4038";
+        src = fetchurl {
+          url = "https://api.github.com/repos/ssddanbrown/HtmlDiff/zipball/58f81857c02b50b199273edb4cc339876b5a4038";
+          sha256 = "0ixsi2s1igvciwnal1v2w654n4idbfs8ipyiixch7k5nzxl4g7wm";
+        };
+      };
+    };
+    "ssddanbrown/symfony-mailer" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "ssddanbrown-symfony-mailer-2219dcdc5f58e4f382ce8f1e6942d16982aa3012";
+        src = fetchurl {
+          url = "https://api.github.com/repos/ssddanbrown/symfony-mailer/zipball/2219dcdc5f58e4f382ce8f1e6942d16982aa3012";
+          sha256 = "14j99gr09mvgjf6jjxbw50zay8n9mg6c0w429hz3vrfaijc2ih8c";
+        };
+      };
+    };
+    "symfony/console" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-console-c3ebc83d031b71c39da318ca8b7a07ecc67507ed";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed";
+          sha256 = "1vvdw2fg08x9788m50isspi06n0lhw6c6nif3di1snxfq0sgb1np";
+        };
+      };
+    };
+    "symfony/css-selector" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-css-selector-f1d00bddb83a4cb2138564b2150001cb6ce272b1";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/css-selector/zipball/f1d00bddb83a4cb2138564b2150001cb6ce272b1";
+          sha256 = "0nl94wjr5sm4yrx9y0vwk4dzh1hm17f1n3d71hmj7biyzds0474i";
+        };
+      };
+    };
+    "symfony/deprecation-contracts" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-deprecation-contracts-26954b3d62a6c5fd0ea8a2a00c0353a14978d05c";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c";
+          sha256 = "1wlaj9ngbyjmgr92gjyf7lsmjfswyh8vpbzq5rdzaxjb6bcsj3dp";
+        };
+      };
+    };
+    "symfony/error-handler" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-error-handler-c7df52182f43a68522756ac31a532dd5b1e6db67";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/error-handler/zipball/c7df52182f43a68522756ac31a532dd5b1e6db67";
+          sha256 = "1dqr0n3w6zmk96q7x8pz1przkiyb2kyg5mw3d1nmnyry8dryv7c8";
+        };
+      };
+    };
+    "symfony/event-dispatcher" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-event-dispatcher-2eaf8e63bc5b8cefabd4a800157f0d0c094f677a";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/event-dispatcher/zipball/2eaf8e63bc5b8cefabd4a800157f0d0c094f677a";
+          sha256 = "0wwphxh21n502wgldh3kqqhvl1zxh2yncbadwwh05d8sp5mz0ysn";
+        };
+      };
+    };
+    "symfony/event-dispatcher-contracts" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-event-dispatcher-contracts-7bc61cc2db649b4637d331240c5346dcc7708051";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7bc61cc2db649b4637d331240c5346dcc7708051";
+          sha256 = "1crx2j4g5jn904fwk7919ar9zpyfd5bvgm80lmyg15kinsjm3w4i";
+        };
+      };
+    };
+    "symfony/finder" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-finder-5cc9cac6586fc0c28cd173780ca696e419fefa11";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/finder/zipball/5cc9cac6586fc0c28cd173780ca696e419fefa11";
+          sha256 = "1f0sbxczwcrzxb03cc2rshfzdrkjfg7nwkbvvi449qscaq1qx2dc";
+        };
+      };
+    };
+    "symfony/http-foundation" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-http-foundation-e16b2676a4b3b1fa12378a20b29c364feda2a8d6";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/http-foundation/zipball/e16b2676a4b3b1fa12378a20b29c364feda2a8d6";
+          sha256 = "0d2fgzcxi7sq7j8l1lg2kpfsr6p1xk1lxdjyqr63vihm34i8p42g";
+        };
+      };
+    };
+    "symfony/http-kernel" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-http-kernel-6dc70833fd0ef5e861e17c7854c12d7d86679349";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/http-kernel/zipball/6dc70833fd0ef5e861e17c7854c12d7d86679349";
+          sha256 = "1j1z911g4nsx7wjg14q1g7y98qj1k4crxnwxi97i4cjnyqihcj2r";
+        };
+      };
+    };
+    "symfony/mime" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-mime-d7052547a0070cbeadd474e172b527a00d657301";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/mime/zipball/d7052547a0070cbeadd474e172b527a00d657301";
+          sha256 = "005jfcpcdn8p2qqv1kyh14jijx36n3rrh9v9a9immfdr0gyv22ca";
+        };
+      };
+    };
+    "symfony/polyfill-ctype" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-polyfill-ctype-ef4d7e442ca910c4764bce785146269b30cb5fc4";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4";
+          sha256 = "16wr6dp9yr4wks11d1qjyzpc343ri2nr7q7fmrnp3jhmp949rppy";
+        };
+      };
+    };
+    "symfony/polyfill-intl-grapheme" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-polyfill-intl-grapheme-32a9da87d7b3245e09ac426c83d334ae9f06f80f";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f";
+          sha256 = "03wk7yxavld4jnvavy7m2d3xxn5h4938wypgwjkblgx8n7s93jiq";
+        };
+      };
+    };
+    "symfony/polyfill-intl-idn" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-polyfill-intl-idn-a287ed7475f85bf6f61890146edbc932c0fff919";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919";
+          sha256 = "14x9hv01fn5dmpkm7480lgzhz4lqdi3w1hlkh3sjpb6ic87k0wc1";
+        };
+      };
+    };
+    "symfony/polyfill-intl-normalizer" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-polyfill-intl-normalizer-bc45c394692b948b4d383a08d7753968bed9a83d";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d";
+          sha256 = "1zq1kklvjl4zj2v6yjzg7rv6ibvhxfymgi2xb0m5cw9r6i63rinw";
+        };
+      };
+    };
+    "symfony/polyfill-mbstring" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-polyfill-mbstring-9773676c8a1bb1f8d4340a62efe641cf76eda7ec";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec";
+          sha256 = "1jpa4wwjfdkkhdpisviy1p4fhik00cldj5msipwl0izkia1d2qgf";
+        };
+      };
+    };
+    "symfony/polyfill-php72" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-polyfill-php72-861391a8da9a04cbad2d232ddd9e4893220d6e25";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25";
+          sha256 = "0b4nw7x6c7jjn9bvkpqjnpszx647lncyswpk2iz57c1xl5dqywvh";
+        };
+      };
+    };
+    "symfony/polyfill-php80" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-polyfill-php80-87b68208d5c1188808dd7839ee1e6c8ec3b02f1b";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b";
+          sha256 = "1pn6dzj8b3h8851w3y6mj5qrwklwky5w71v4m455553qlga5cfr7";
+        };
+      };
+    };
+    "symfony/polyfill-php81" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-polyfill-php81-c565ad1e63f30e7477fc40738343c62b40bc672d";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/polyfill-php81/zipball/c565ad1e63f30e7477fc40738343c62b40bc672d";
+          sha256 = "0xy6jjnqvc6v1s7wvdm1yplblpbh43ilis93vjrlv7hc7i6ygfzg";
+        };
+      };
+    };
+    "symfony/polyfill-uuid" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-polyfill-uuid-3abdd21b0ceaa3000ee950097bc3cf9efc137853";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/polyfill-uuid/zipball/3abdd21b0ceaa3000ee950097bc3cf9efc137853";
+          sha256 = "15g5ng1bcca4nqxjrcjabc1v679zl6xwm1wwfngvww1hvrbgd98d";
+        };
+      };
+    };
+    "symfony/process" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-process-2114fd60f26a296cc403a7939ab91478475a33d4";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/process/zipball/2114fd60f26a296cc403a7939ab91478475a33d4";
+          sha256 = "1rpcl0qayf0jysfn95c4s73r7fl48sng4m5flxy099z6m6bblwq1";
+        };
+      };
+    };
+    "symfony/routing" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-routing-e56ca9b41c1ec447193474cd86ad7c0b547755ac";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/routing/zipball/e56ca9b41c1ec447193474cd86ad7c0b547755ac";
+          sha256 = "0qsx525fhqnx6g5rn8lavzpqccrg2ixrp88p1g4yjr8x7i2im5nd";
+        };
+      };
+    };
+    "symfony/service-contracts" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-service-contracts-d78d39c1599bd1188b8e26bb341da52c3c6d8a66";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66";
+          sha256 = "1cgbn2yx2fyrc3c1d85vdriiwwifr1sdg868f3rhq9bh78f03z99";
+        };
+      };
+    };
+    "symfony/string" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-string-d9e72497367c23e08bf94176d2be45b00a9d232a";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a";
+          sha256 = "0k4vvcjfdp2dni8gzq4rn8d6n0ivd38sfna70lgsh8vlc8rrlhpf";
+        };
+      };
+    };
+    "symfony/translation" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-translation-9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/translation/zipball/9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f";
+          sha256 = "12c13k5ljch06g8xp28kkpv0ml67hy086rk25mzd94hjpawrs4x2";
+        };
+      };
+    };
+    "symfony/translation-contracts" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-translation-contracts-acbfbb274e730e5a0236f619b6168d9dedb3e282";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282";
+          sha256 = "1r496j63a6q3ch0ax76qa1apmc4iqf41zc8rf6yn8vkir3nzkqr0";
+        };
+      };
+    };
+    "symfony/uid" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-uid-6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/uid/zipball/6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d";
+          sha256 = "12r2jgmwwchmq4apgmb2h1hy6i4cznjpc94976h2qzy3q3yp7zyq";
+        };
+      };
+    };
+    "symfony/var-dumper" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "symfony-var-dumper-eb980457fa6899840fe1687e8627a03a7d8a3d52";
+        src = fetchurl {
+          url = "https://api.github.com/repos/symfony/var-dumper/zipball/eb980457fa6899840fe1687e8627a03a7d8a3d52";
+          sha256 = "183igs4i74kljxyq7azpg59wb281mlvy1xgqnb4pkz4dw50jgc2k";
+        };
+      };
+    };
+    "tijsverkoyen/css-to-inline-styles" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "tijsverkoyen-css-to-inline-styles-83ee6f38df0a63106a9e4536e3060458b74ccedb";
+        src = fetchurl {
+          url = "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/83ee6f38df0a63106a9e4536e3060458b74ccedb";
+          sha256 = "1ahj49c7qz6m3y65jd18cz2c8cg6zqhkmnsrqrw1bf3s8ly9a9bp";
+        };
+      };
+    };
+    "vlucas/phpdotenv" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "vlucas-phpdotenv-2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4";
+        src = fetchurl {
+          url = "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4";
+          sha256 = "0zb5gm5i6rnmm9zc4mi3wkkhpgciaa76w8jyxnw914xwq1xqzivx";
+        };
+      };
+    };
+    "voku/portable-ascii" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "voku-portable-ascii-b56450eed252f6801410d810c8e1727224ae0743";
+        src = fetchurl {
+          url = "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743";
+          sha256 = "0gwlv1hr6ycrf8ik1pnvlwaac8cpm8sa1nf4d49s8rp4k2y5anyl";
+        };
+      };
+    };
+    "webmozart/assert" = {
+      targetDir = "";
+      src = composerEnv.buildZipPackage {
+        name = "webmozart-assert-11cb2199493b2f8a3b53e7f19068fc6aac760991";
+        src = fetchurl {
+          url = "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991";
+          sha256 = "18qiza1ynwxpi6731jx1w5qsgw98prld1lgvfk54z92b1nc7psix";
+        };
+      };
+    };
+  };
+  devPackages = {};
+in
+composerEnv.buildPackage {
+  inherit packages devPackages noDev;
+  name = "bookstack";
+  src = composerEnv.filterSrc ./.;
+  executable = false;
+  symlinkDependencies = false;
+  meta = {
+    license = "MIT";
+  };
+}
+
diff --git a/nixpkgs/pkgs/servers/web-apps/bookstack/update.sh b/nixpkgs/pkgs/servers/web-apps/bookstack/update.sh
new file mode 100755
index 000000000000..f8db51edf745
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/bookstack/update.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env nix-shell
+#! nix-shell -i bash -p nix curl jq nix-update
+
+# check if composer2nix is installed
+if ! command -v composer2nix &> /dev/null; then
+  echo "Please install composer2nix (https://github.com/svanderburg/composer2nix) to run this script."
+  exit 1
+fi
+
+CURRENT_VERSION=$(nix eval -f ../../../.. --raw bookstack.version)
+TARGET_VERSION_REMOTE=$(curl https://api.github.com/repos/bookstackapp/bookstack/releases/latest | jq -r ".tag_name")
+TARGET_VERSION=${TARGET_VERSION_REMOTE:1}
+BOOKSTACK=https://github.com/bookstackapp/bookstack/raw/$TARGET_VERSION_REMOTE
+SHA256=$(nix-prefetch-url --unpack "https://github.com/bookstackapp/bookstack/archive/v$TARGET_VERSION/bookstack.tar.gz")
+
+if [[ "$CURRENT_VERSION" == "$TARGET_VERSION" ]]; then
+  echo "bookstack is up-to-date: ${CURRENT_VERSION}"
+  exit 0
+fi
+
+curl -LO "$BOOKSTACK/composer.json"
+curl -LO "$BOOKSTACK/composer.lock"
+
+composer2nix --name "bookstack" \
+  --composition=composition.nix \
+  --no-dev
+rm composer.json composer.lock
+
+# change version number
+sed -e "s/version =.*;/version = \"$TARGET_VERSION\";/g" \
+    -e "s/sha256 =.*;/sha256 = \"$SHA256\";/g" \
+    -i ./default.nix
+
+# fix composer-env.nix
+sed -e "s/stdenv\.lib/lib/g" \
+    -e '3s/stdenv, writeTextFile/stdenv, lib, writeTextFile/' \
+    -i ./composer-env.nix
+
+# fix composition.nix
+sed -e '7s/stdenv writeTextFile/stdenv lib writeTextFile/' \
+    -i composition.nix
+
+# fix missing newline
+echo "" >> composition.nix
+echo "" >> php-packages.nix
+
+cd ../../../..
+nix-build -A bookstack
+
+exit $?
diff --git a/nixpkgs/pkgs/servers/web-apps/changedetection-io/default.nix b/nixpkgs/pkgs/servers/web-apps/changedetection-io/default.nix
new file mode 100644
index 000000000000..4d058e916ab7
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/changedetection-io/default.nix
@@ -0,0 +1,85 @@
+{ lib
+, fetchFromGitHub
+, python3
+}:
+
+python3.pkgs.buildPythonApplication rec {
+  pname = "changedetection-io";
+  version = "0.45.16";
+  format = "setuptools";
+
+  src = fetchFromGitHub {
+    owner = "dgtlmoon";
+    repo = "changedetection.io";
+    rev = version;
+    hash = "sha256-ln522U3XqZfhvLvMEzrqXV3SjhpgnrRk2MxQQRBL5VU=";
+  };
+
+  postPatch = ''
+    substituteInPlace requirements.txt \
+      --replace "apprise~=1.7.1" "apprise" \
+      --replace "cryptography~=3.4" "cryptography" \
+      --replace "dnspython~=2.4" "dnspython" \
+      --replace "pytest ~=7.2" "" \
+      --replace "pytest-flask ~=1.2" "" \
+      --replace "selenium~=4.14.0" "selenium" \
+      --replace "werkzeug~=3.0" "werkzeug"
+  '';
+
+  propagatedBuildInputs = with python3.pkgs; [
+    apprise
+    beautifulsoup4
+    brotli
+    chardet
+    cryptography
+    dnspython
+    eventlet
+    feedgen
+    flask
+    flask-compress
+    flask-cors
+    flask-expects-json
+    flask-login
+    flask-paginate
+    flask-restful
+    flask-wtf
+    inscriptis
+    jinja2
+    jinja2-time
+    jsonpath-ng
+    jq
+    loguru
+    lxml
+    paho-mqtt
+    pillow
+    playwright
+    pyee
+    pyppeteer
+    pytz
+    requests
+    selenium
+    setuptools
+    timeago
+    urllib3
+    validators
+    werkzeug
+    wtforms
+  ] ++ requests.optional-dependencies.socks;
+
+  # tests can currently not be run in one pytest invocation and without docker
+  doCheck = false;
+
+  nativeCheckInputs = with python3.pkgs; [
+    pytest-flask
+    pytestCheckHook
+  ];
+
+  meta = with lib; {
+    description = "Self-hosted free open source website change detection tracking, monitoring and notification service";
+    homepage = "https://github.com/dgtlmoon/changedetection.io";
+    changelog = "https://github.com/dgtlmoon/changedetection.io/releases/tag/${version}";
+    license = licenses.asl20;
+    maintainers = with maintainers; [ mikaelfangel ];
+    mainProgram = "changedetection.io";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/action_mailer_ca_cert.patch b/nixpkgs/pkgs/servers/web-apps/discourse/action_mailer_ca_cert.patch
new file mode 100644
index 000000000000..d6a4ff8f2a78
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/action_mailer_ca_cert.patch
@@ -0,0 +1,12 @@
+diff --git a/config/environments/production.rb b/config/environments/production.rb
+index 6b73c82e9d..0cefea6fc0 100644
+--- a/config/environments/production.rb
++++ b/config/environments/production.rb
+@@ -32,5 +32,6 @@ Discourse::Application.configure do
+       user_name: GlobalSetting.smtp_user_name,
+       password: GlobalSetting.smtp_password,
+       authentication: GlobalSetting.smtp_authentication,
++      ca_file: "/etc/ssl/certs/ca-certificates.crt",
+       enable_starttls_auto: GlobalSetting.smtp_enable_start_tls,
+       open_timeout: GlobalSetting.smtp_open_timeout,
+       read_timeout: GlobalSetting.smtp_read_timeout
\ No newline at end of file
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/admin_create.patch b/nixpkgs/pkgs/servers/web-apps/discourse/admin_create.patch
new file mode 100644
index 000000000000..691b806dfd65
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/admin_create.patch
@@ -0,0 +1,48 @@
+diff --git a/lib/tasks/admin.rake b/lib/tasks/admin.rake
+index 37ef651f2b..b775129498 100644
+--- a/lib/tasks/admin.rake
++++ b/lib/tasks/admin.rake
+@@ -107,3 +107,43 @@ task "admin:create" => :environment do
+   end
+ 
+ end
++
++desc "Creates a forum administrator noninteractively"
++task "admin:create_noninteractively" => :environment do
++  email = ENV["ADMIN_EMAIL"]
++  existing_user = User.find_by_email(email)
++
++  # check if user account already exixts
++  if existing_user
++    admin = existing_user
++  else
++    # create new user
++    admin = User.new
++  end
++
++  admin.email = email
++  admin.name = ENV["ADMIN_NAME"]
++  admin.username = ENV["ADMIN_USERNAME"]
++
++  password = ENV["ADMIN_PASSWORD"]
++  unless admin.confirm_password?(password)
++    admin.password = password
++    puts "Admin password set!"
++  end
++
++  admin.active = true
++
++  # save/update user account
++  saved = admin.save
++  raise admin.errors.full_messages.join("\n") unless saved
++
++  puts "Account created successfully with username #{admin.username}" unless existing_user
++
++  # grant admin privileges
++  admin.grant_admin!
++  if admin.trust_level < 1
++    admin.change_trust_level!(1)
++  end
++  admin.email_tokens.update_all confirmed: true
++  admin.activate
++end
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/asserts_patch-package_from_path.patch b/nixpkgs/pkgs/servers/web-apps/discourse/asserts_patch-package_from_path.patch
new file mode 100644
index 000000000000..9f7d98b069f4
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/asserts_patch-package_from_path.patch
@@ -0,0 +1,13 @@
+diff --git a/app/assets/javascripts/discourse/package.json b/app/assets/javascripts/discourse/package.json
+index 9e4533d2..e57f8a5f 100644
+--- a/app/assets/javascripts/discourse/package.json
++++ b/app/assets/javascripts/discourse/package.json
+@@ -14,7 +14,7 @@
+     "build": "ember build",
+     "start": "ember serve",
+     "test": "ember test",
+-    "postinstall": "yarn --silent --cwd .. patch-package"
++    "postinstall": "patch-package"
+   },
+   "dependencies": {
+     "@babel/core": "^7.21.4",
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/assets_esbuild_from_path.patch b/nixpkgs/pkgs/servers/web-apps/discourse/assets_esbuild_from_path.patch
new file mode 100644
index 000000000000..fd40d27ca8b5
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/assets_esbuild_from_path.patch
@@ -0,0 +1,13 @@
+diff --git a/lib/discourse_js_processor.rb b/lib/discourse_js_processor.rb
+index 3fee4259af9..53cc3107f46 100644
+--- a/lib/discourse_js_processor.rb
++++ b/lib/discourse_js_processor.rb
+@@ -111,8 +111,6 @@ class DiscourseJsProcessor
+ 
+     def self.generate_js_processor
+       Discourse::Utils.execute_command(
+-        "yarn",
+-        "--silent",
+         "esbuild",
+         "--log-level=warning",
+         "--bundle",
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/assets_rake_command.patch b/nixpkgs/pkgs/servers/web-apps/discourse/assets_rake_command.patch
new file mode 100644
index 000000000000..b37b6d1d7994
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/assets_rake_command.patch
@@ -0,0 +1,13 @@
+diff --git a/lib/tasks/assets.rake b/lib/tasks/assets.rake
+index 68b5db61ac..d460b5753e 100644
+--- a/lib/tasks/assets.rake
++++ b/lib/tasks/assets.rake
+@@ -19,7 +19,7 @@ task 'assets:precompile:before' do
+ 
+     if only_assets_precompile_remaining
+       # Using exec to free up Rails app memory during ember build
+-      exec "#{compile_command} && EMBER_CLI_COMPILE_DONE=1 bin/rake assets:precompile"
++      exec "#{compile_command} && EMBER_CLI_COMPILE_DONE=1 bundle exec rake assets:precompile"
+     else
+       system compile_command
+     end
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/auto_generated_path.patch b/nixpkgs/pkgs/servers/web-apps/discourse/auto_generated_path.patch
new file mode 100644
index 000000000000..c80e4a48ecd9
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/auto_generated_path.patch
@@ -0,0 +1,13 @@
+diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb
+index 8482ff0210..826d111d65 100644
+--- a/lib/plugin/instance.rb
++++ b/lib/plugin/instance.rb
+@@ -455,7 +455,7 @@ class Plugin::Instance
+   end
+ 
+   def auto_generated_path
+-    File.dirname(path) << "/auto_generated"
++    "#{Rails.root}/public/assets/auto_generated_plugin_assets/#{name}"
+   end
+ 
+   def after_initialize(&block)
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/default.nix
new file mode 100644
index 000000000000..b1e24720450e
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/default.nix
@@ -0,0 +1,414 @@
+{ stdenv
+, pkgs
+, makeWrapper
+, runCommand
+, lib
+, writeShellScript
+, fetchFromGitHub
+, bundlerEnv
+, callPackage
+
+, ruby_3_2
+, replace
+, gzip
+, gnutar
+, git
+, cacert
+, util-linux
+, gawk
+, nettools
+, imagemagick
+, optipng
+, pngquant
+, libjpeg
+, jpegoptim
+, gifsicle
+, jhead
+, oxipng
+, libpsl
+, redis
+, postgresql
+, which
+, brotli
+, procps
+, rsync
+, icu
+, fetchYarnDeps
+, yarn
+, fixup_yarn_lock
+, nodePackages
+, nodejs_18
+, jq
+, moreutils
+, terser
+
+, plugins ? []
+}@args:
+
+let
+  version = "3.1.0";
+
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse";
+    rev = "v${version}";
+    sha256 = "sha256-Iv7VSnK8nZDpmIwIRPedSWlftABKuMOQ4MXDGpjuWrY=";
+  };
+
+  ruby = ruby_3_2;
+
+  runtimeDeps = [
+    # For backups, themes and assets
+    rubyEnv.wrappedRuby
+    rsync
+    gzip
+    gnutar
+    git
+    brotli
+
+    # Misc required system utils
+    which
+    procps       # For ps and kill
+    util-linux   # For renice
+    gawk
+    nettools     # For hostname
+
+    # Image optimization
+    imagemagick
+    optipng
+    oxipng
+    pngquant
+    libjpeg
+    jpegoptim
+    gifsicle
+    nodePackages.svgo
+    jhead
+  ];
+
+  runtimeEnv = {
+    HOME = "/run/discourse/home";
+    RAILS_ENV = "production";
+    UNICORN_LISTENER = "/run/discourse/sockets/unicorn.sock";
+  };
+
+  mkDiscoursePlugin =
+    { name ? null
+    , pname ? null
+    , version ? null
+    , meta ? null
+    , bundlerEnvArgs ? {}
+    , preserveGemsDir ? false
+    , src
+    , ...
+    }@args:
+    let
+      rubyEnv = bundlerEnv (bundlerEnvArgs // {
+        inherit name pname version ruby;
+      });
+    in
+      stdenv.mkDerivation (builtins.removeAttrs args [ "bundlerEnvArgs" ] // {
+        pluginName = if name != null then name else "${pname}-${version}";
+        dontConfigure = true;
+        dontBuild = true;
+        installPhase = ''
+          runHook preInstall
+          mkdir -p $out
+          cp -r * $out/
+        '' + lib.optionalString (bundlerEnvArgs != {}) (
+          if preserveGemsDir then ''
+            cp -r ${rubyEnv}/lib/ruby/gems/* $out/gems/
+          ''
+          else ''
+            if [[ -e $out/gems ]]; then
+              echo "Warning: The repo contains a 'gems' directory which will be removed!"
+              echo "         If you need to preserve it, set 'preserveGemsDir = true'."
+              rm -r $out/gems
+            fi
+            ln -sf ${rubyEnv}/lib/ruby/gems $out/gems
+          '' + ''
+          runHook postInstall
+        '');
+      });
+
+  rake = runCommand "discourse-rake" {
+    nativeBuildInputs = [ makeWrapper ];
+  } ''
+    mkdir -p $out/bin
+    makeWrapper ${rubyEnv}/bin/rake $out/bin/discourse-rake \
+        ${lib.concatStrings (lib.mapAttrsToList (name: value: "--set ${name} '${value}' ") runtimeEnv)} \
+        --prefix PATH : ${lib.makeBinPath runtimeDeps} \
+        --set RAKEOPT '-f ${discourse}/share/discourse/Rakefile' \
+        --chdir '${discourse}/share/discourse'
+  '';
+
+  rubyEnv = bundlerEnv {
+    name = "discourse-ruby-env-${version}";
+    inherit version ruby;
+    gemdir = ./rubyEnv;
+    gemset =
+      let
+        gems = import ./rubyEnv/gemset.nix;
+      in
+        gems // {
+          mini_racer = gems.mini_racer // {
+            buildInputs = [ icu ];
+            dontBuild = false;
+            NIX_LDFLAGS = "-licui18n";
+          };
+          libv8-node =
+            let
+              noopScript = writeShellScript "noop" "exit 0";
+              linkFiles = writeShellScript "link-files" ''
+                cd ../..
+
+                mkdir -p vendor/v8/${stdenv.hostPlatform.system}/libv8/obj/
+                ln -s "${nodejs_18.libv8}/lib/libv8.a" vendor/v8/${stdenv.hostPlatform.system}/libv8/obj/libv8_monolith.a
+
+                ln -s ${nodejs_18.libv8}/include vendor/v8/include
+
+                mkdir -p ext/libv8-node
+                echo '--- !ruby/object:Libv8::Node::Location::Vendor {}' >ext/libv8-node/.location.yml
+              '';
+            in gems.libv8-node // {
+              dontBuild = false;
+              postPatch = ''
+                cp ${noopScript} libexec/build-libv8
+                cp ${noopScript} libexec/build-monolith
+                cp ${noopScript} libexec/download-node
+                cp ${noopScript} libexec/extract-node
+                cp ${linkFiles} libexec/inject-libv8
+              '';
+            };
+          mini_suffix = gems.mini_suffix // {
+            propagatedBuildInputs = [ libpsl ];
+            dontBuild = false;
+            # Use our libpsl instead of the vendored one, which isn't
+            # available for aarch64. It has to be called
+            # libpsl.x86_64.so or it isn't found.
+            postPatch = ''
+              cp $(readlink -f ${lib.getLib libpsl}/lib/libpsl.so) vendor/libpsl.x86_64.so
+            '';
+          };
+        };
+
+    groups = [
+      "default" "assets" "development" "test"
+    ];
+  };
+
+  assets = stdenv.mkDerivation {
+    pname = "discourse-assets";
+    inherit version src;
+
+    yarnOfflineCache = fetchYarnDeps {
+      yarnLock = src + "/app/assets/javascripts/yarn.lock";
+      sha256 = "0sclrv3303dgg3r08dwhd1yvi3pvlnvnikn300vjsh6c71fnzhnj";
+    };
+
+    nativeBuildInputs = runtimeDeps ++ [
+      postgresql
+      redis
+      nodePackages.uglify-js
+      terser
+      nodePackages.patch-package
+      yarn
+      nodejs_18
+      jq
+      moreutils
+    ];
+
+    outputs = [ "out" "javascripts" ];
+
+    patches = [
+      # Use the Ruby API version in the plugin gem path, to match the
+      # one constructed by bundlerEnv
+      ./plugin_gem_api_version.patch
+
+      # Change the path to the auto generated plugin assets, which
+      # defaults to the plugin's directory and isn't writable at the
+      # time of asset generation
+      ./auto_generated_path.patch
+
+      # Fix the rake command used to recursively execute itself in the
+      # assets precompilation task.
+      ./assets_rake_command.patch
+
+      # `app/assets/javascripts/discourse/package.json`'s postinstall
+      # hook tries to call `../node_modules/.bin/patch-package`, which
+      # hasn't been `patchShebangs`-ed yet. So instead we just use
+      # `patch-package` from `nativeBuildInputs`.
+      ./asserts_patch-package_from_path.patch
+    ];
+
+    # We have to set up an environment that is close enough to
+    # production ready or the assets:precompile task refuses to
+    # run. This means that Redis and PostgreSQL has to be running and
+    # database migrations performed.
+    preBuild = ''
+      # Yarn wants a real home directory to write cache, config, etc to
+      export HOME=$NIX_BUILD_TOP/fake_home
+
+      # Make yarn install packages from our offline cache, not the registry
+      yarn config --offline set yarn-offline-mirror $yarnOfflineCache
+
+      # Fixup "resolved"-entries in yarn.lock to match our offline cache
+      ${fixup_yarn_lock}/bin/fixup_yarn_lock app/assets/javascripts/yarn.lock
+
+      export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
+
+      find app/assets/javascripts -name package.json -print0 \
+        | xargs -0 -I {} bash -c "jq 'del(.scripts.postinstall)' -r <{} | sponge {}"
+      yarn install --offline --cwd app/assets/javascripts/discourse
+
+      patchShebangs app/assets/javascripts/node_modules/
+
+      # Run `patch-package` AFTER the corresponding shebang inside `.bin/patch-package`
+      # got patched. Otherwise this will fail with
+      #     /bin/sh: line 1: /build/source/app/assets/javascripts/node_modules/.bin/patch-package: cannot execute: required file not found
+      pushd app/assets/javascripts &>/dev/null
+        yarn run patch-package
+      popd &>/dev/null
+
+      redis-server >/dev/null &
+
+      initdb -A trust $NIX_BUILD_TOP/postgres >/dev/null
+      postgres -D $NIX_BUILD_TOP/postgres -k $NIX_BUILD_TOP >/dev/null &
+      export PGHOST=$NIX_BUILD_TOP
+
+      echo "Waiting for Redis and PostgreSQL to be ready.."
+      while ! redis-cli --scan >/dev/null || ! psql -l >/dev/null; do
+        sleep 0.1
+      done
+
+      psql -d postgres -tAc 'CREATE USER "discourse"'
+      psql -d postgres -tAc 'CREATE DATABASE "discourse" OWNER "discourse"'
+      psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm"
+      psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS hstore"
+
+      # Create a temporary home dir to stop bundler from complaining
+      mkdir $NIX_BUILD_TOP/tmp_home
+      export HOME=$NIX_BUILD_TOP/tmp_home
+
+      ${lib.concatMapStringsSep "\n" (p: "ln -sf ${p} plugins/${p.pluginName or ""}") plugins}
+
+      export RAILS_ENV=production
+
+      bundle exec rake db:migrate >/dev/null
+      chmod -R +w tmp
+    '';
+
+    buildPhase = ''
+      runHook preBuild
+
+      bundle exec rake assets:precompile
+
+      runHook postBuild
+    '';
+
+    installPhase = ''
+      runHook preInstall
+
+      mv public/assets $out
+
+      rm -r app/assets/javascripts/plugins
+      mv app/assets/javascripts $javascripts
+      ln -sf /run/discourse/assets/javascripts/plugins $javascripts/plugins
+
+      runHook postInstall
+    '';
+  };
+
+  discourse = stdenv.mkDerivation {
+    pname = "discourse";
+    inherit version src;
+
+    buildInputs = [
+      rubyEnv rubyEnv.wrappedRuby rubyEnv.bundler
+    ];
+
+    patches = [
+      # Load a separate NixOS site settings file
+      ./nixos_defaults.patch
+
+      # Add a noninteractive admin creation task
+      ./admin_create.patch
+
+      # Add the path to the CA cert bundle to make TLS work
+      ./action_mailer_ca_cert.patch
+
+      # Log Unicorn messages to the journal and make request timeout
+      # configurable
+      ./unicorn_logging_and_timeout.patch
+
+      # Use the Ruby API version in the plugin gem path, to match the
+      # one constructed by bundlerEnv
+      ./plugin_gem_api_version.patch
+
+      # Change the path to the auto generated plugin assets, which
+      # defaults to the plugin's directory and isn't writable at the
+      # time of asset generation
+      ./auto_generated_path.patch
+
+      # Make sure the notification email setting applies
+      ./notification_email.patch
+    ];
+
+    postPatch = ''
+      # Always require lib-files and application.rb through their store
+      # path, not their relative state directory path. This gets rid of
+      # warnings and means we don't have to link back to lib from the
+      # state directory.
+      find config -type f -name "*.rb" -execdir \
+        sed -Ei "s,(\.\./)+(lib|app)/,$out/share/discourse/\2/," {} \;
+      find config -maxdepth 1 -type f -name "*.rb" -execdir \
+        sed -Ei "s,require_relative (\"|')([[:alnum:]].*)(\"|'),require_relative '$out/share/discourse/config/\2'," {} \;
+    '';
+
+    buildPhase = ''
+      runHook preBuild
+
+      mv config config.dist
+      mv public public.dist
+
+      runHook postBuild
+    '';
+
+    installPhase = ''
+      runHook preInstall
+
+      mkdir -p $out/share
+      cp -r . $out/share/discourse
+      rm -r $out/share/discourse/log
+      ln -sf /var/log/discourse $out/share/discourse/log
+      ln -sf /var/lib/discourse/tmp $out/share/discourse/tmp
+      ln -sf /run/discourse/config $out/share/discourse/config
+      ln -sf /run/discourse/public $out/share/discourse/public
+      ln -sf ${assets} $out/share/discourse/public.dist/assets
+      rm -r $out/share/discourse/app/assets/javascripts
+      ln -sf ${assets.javascripts} $out/share/discourse/app/assets/javascripts
+      ${lib.concatMapStringsSep "\n" (p: "ln -sf ${p} $out/share/discourse/plugins/${p.pluginName or ""}") plugins}
+
+      runHook postInstall
+    '';
+
+    meta = with lib; {
+      homepage = "https://www.discourse.org/";
+      platforms = platforms.linux;
+      maintainers = with maintainers; [ talyz ];
+      license = licenses.gpl2Plus;
+      description = "Discourse is an open source discussion platform";
+    };
+
+    passthru = {
+      inherit rubyEnv runtimeEnv runtimeDeps rake mkDiscoursePlugin assets;
+      enabledPlugins = plugins;
+      plugins = callPackage ./plugins/all-plugins.nix { inherit mkDiscoursePlugin; };
+      ruby = rubyEnv.wrappedRuby;
+      tests = import ../../../../nixos/tests/discourse.nix {
+        inherit (stdenv) system;
+        inherit pkgs;
+        package = pkgs.discourse.override args;
+      };
+    };
+  };
+in discourse
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/how_to_update.md b/nixpkgs/pkgs/servers/web-apps/discourse/how_to_update.md
new file mode 100644
index 000000000000..c402325babc8
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/how_to_update.md
@@ -0,0 +1,24 @@
+To update discourse, do the following:
+
+1. Switch to and work from the `master` branch and the directory this
+   file is in.
+2. Run `./update.py print-diffs` and update the nginx settings and
+   backend settings accordingly. If you don't know how to, ask for
+   help - do not skip this step!
+3. Run `./update.py update`.
+4. Run `nix build -L -f ../../../../ discourse.tests` to make sure the
+   update works. Also test manually, if possible.
+5. If the update works, commit it. If not, apply necessary fixes and
+   commit. No manual fixes that would be overwritten by the
+   `./update.py` script should be committed - the script should be
+   fixed instead.
+6. Run `./update.py update-mail-receiver`. If there's an update, do
+   step 4 and 5 again.
+7. Run `./update.py update-plugins`.
+8. Run `nix build -L -f ../../../../ discourseAllPlugins.tests` to
+   make sure the plugins build and discourse starts with them. Also
+   test manually, if possible.
+9. If the update works, commit it. If not, apply necessary fixes and
+   commit. No manual fixes that would be overwritten by the
+   `./update.py` script should be committed - the script should be
+   fixed instead.
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/mail_receiver/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/mail_receiver/default.nix
new file mode 100644
index 000000000000..139e6718ed5e
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/mail_receiver/default.nix
@@ -0,0 +1,39 @@
+{ stdenv, lib, fetchFromGitHub, ruby, makeWrapper, replace }:
+
+stdenv.mkDerivation rec {
+  pname = "discourse-mail-receiver";
+  version = "4.0.7";
+
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "mail-receiver";
+    rev = "v${version}";
+    sha256 = "0grifm5qyqazq63va3w26xjqnxwmfixhx0fx0zy7kd39378wwa6i";
+  };
+
+  nativeBuildInputs = [ replace makeWrapper ];
+  buildInputs = [ ruby ];
+
+  dontBuild = true;
+
+  installPhase = ''
+    mkdir -p $out/bin
+
+    replace-literal -f -r -e /etc/postfix /run/discourse-mail-receiver .
+
+    cp -r receive-mail discourse-smtp-fast-rejection $out/bin/
+    cp -r lib $out/
+
+    wrapProgram $out/bin/receive-mail --set RUBYLIB $out/lib
+    wrapProgram $out/bin/discourse-smtp-fast-rejection --set RUBYLIB $out/lib
+  '';
+
+  meta = with lib; {
+    homepage = "https://www.discourse.org/";
+    platforms = platforms.linux;
+    maintainers = with maintainers; [ talyz ];
+    license = licenses.mit;
+    description = "A helper program which receives incoming mail for Discourse";
+  };
+
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/nixos_defaults.patch b/nixpkgs/pkgs/servers/web-apps/discourse/nixos_defaults.patch
new file mode 100644
index 000000000000..98dba9b54b90
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/nixos_defaults.patch
@@ -0,0 +1,13 @@
+diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb
+index a6641f967a..a45353504a 100644
+--- a/app/models/site_setting.rb
++++ b/app/models/site_setting.rb
+@@ -21,6 +21,8 @@ class SiteSetting < ActiveRecord::Base
+     end
+   end
+ 
++  load_settings(File.join(Rails.root, 'config', 'nixos_site_settings.json'))
++
+   setup_deprecated_methods
+   client_settings << :available_locales
+ 
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/notification_email.patch b/nixpkgs/pkgs/servers/web-apps/discourse/notification_email.patch
new file mode 100644
index 000000000000..9a64b1c1f9ea
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/notification_email.patch
@@ -0,0 +1,18 @@
+diff --git a/db/fixtures/990_settings.rb b/db/fixtures/990_settings.rb
+deleted file mode 100644
+index 6f21e58813..0000000000
+--- a/db/fixtures/990_settings.rb
++++ /dev/null
+@@ -1,12 +0,0 @@
+-# frozen_string_literal: true
+-
+-if SiteSetting.notification_email == SiteSetting.defaults[:notification_email]
+-  # don't crash for invalid hostname, which is possible in dev
+-  begin
+-    SiteSetting.notification_email = "noreply@#{Discourse.current_hostname}"
+-  rescue Discourse::InvalidParameters
+-    if Rails.env.production?
+-      STDERR.puts "WARNING: Discourse hostname: #{Discourse.current_hostname} is not a valid domain for emails!"
+-    end
+-  end
+-end
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugin_gem_api_version.patch b/nixpkgs/pkgs/servers/web-apps/discourse/plugin_gem_api_version.patch
new file mode 100644
index 000000000000..84fb1d4dad4a
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugin_gem_api_version.patch
@@ -0,0 +1,13 @@
+diff --git a/lib/plugin_gem.rb b/lib/plugin_gem.rb
+index 49882b2cd9..96672df2ea 100644
+--- a/lib/plugin_gem.rb
++++ b/lib/plugin_gem.rb
+@@ -4,7 +4,7 @@ module PluginGem
+   def self.load(path, name, version, opts = nil)
+     opts ||= {}
+ 
+-    gems_path = File.dirname(path) + "/gems/#{RUBY_VERSION}"
++    gems_path = File.dirname(path) + "/gems/#{Gem.ruby_api_version}"
+ 
+     spec_path = gems_path + "/specifications"
+ 
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/README b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/README
new file mode 100644
index 000000000000..e0a88211dae8
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/README
@@ -0,0 +1,4 @@
+Run the nixpkgs/pkgs/servers/web-apps/discourse/update.py script to
+update plugins! See the Plugins section of the Discourse chapter in
+the NixOS manual (https://nixos.org/manual/nixos/unstable/index.html#module-services-discourse)
+for more info.
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/all-plugins.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/all-plugins.nix
new file mode 100644
index 000000000000..4ddb8995b622
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/all-plugins.nix
@@ -0,0 +1,27 @@
+{ mkDiscoursePlugin, newScope, fetchFromGitHub, ... }@args:
+let
+  callPackage = newScope args;
+in
+{
+  discourse-assign = callPackage ./discourse-assign {};
+  discourse-bbcode-color = callPackage ./discourse-bbcode-color {};
+  discourse-calendar = callPackage ./discourse-calendar {};
+  discourse-canned-replies = callPackage ./discourse-canned-replies {};
+  discourse-chat-integration = callPackage ./discourse-chat-integration {};
+  discourse-checklist = callPackage ./discourse-checklist {};
+  discourse-data-explorer = callPackage ./discourse-data-explorer {};
+  discourse-docs = callPackage ./discourse-docs {};
+  discourse-github = callPackage ./discourse-github {};
+  discourse-ldap-auth = callPackage ./discourse-ldap-auth {};
+  discourse-math = callPackage ./discourse-math {};
+  discourse-migratepassword = callPackage ./discourse-migratepassword {};
+  discourse-oauth2-basic = callPackage ./discourse-oauth2-basic {};
+  discourse-openid-connect = callPackage ./discourse-openid-connect {};
+  discourse-prometheus = callPackage ./discourse-prometheus {};
+  discourse-reactions = callPackage ./discourse-reactions {};
+  discourse-saved-searches = callPackage ./discourse-saved-searches {};
+  discourse-solved = callPackage ./discourse-solved {};
+  discourse-spoiler-alert = callPackage ./discourse-spoiler-alert {};
+  discourse-voting = callPackage ./discourse-voting {};
+  discourse-yearly-review = callPackage ./discourse-yearly-review {};
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-assign/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-assign/default.nix
new file mode 100644
index 000000000000..68cd69dcc3a6
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-assign/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-assign";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-assign";
+    rev = "0cbf10b8055370445bd36536e51986bf48bdc57e";
+    sha256 = "sha256-7rJ2zQo1nCHwtVuLJUmdj66Ky2bi4Cpo+22H3DbO1uo=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-docs";
+    maintainers = with maintainers; [ dpausp ];
+    license = licenses.mit;
+    description = "Discourse Plugin for assigning users to a topic";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-bbcode-color/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-bbcode-color/default.nix
new file mode 100644
index 000000000000..266c43e4f8e2
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-bbcode-color/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-bbcode-color";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-bbcode-color";
+    rev = "35aab2e9b92f8b01633d374ea999e7fd59d020d7";
+    sha256 = "sha256-DHckx921EeQysm1UPloCrt43BJetTnZKnTbJGk15NMs=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-bbcode-color";
+    maintainers = with maintainers; [ ryantm ];
+    license = licenses.mit;
+    description = "Support BBCode color tags.";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/Gemfile b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/Gemfile
new file mode 100644
index 000000000000..76faf85df5e2
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/Gemfile
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+# gem "rails"
+gem "rrule", "0.4.4", require: false
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/Gemfile.lock b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/Gemfile.lock
new file mode 100644
index 000000000000..183ead8d51d4
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/Gemfile.lock
@@ -0,0 +1,25 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    activesupport (7.0.8)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 1.6, < 2)
+      minitest (>= 5.1)
+      tzinfo (~> 2.0)
+    concurrent-ruby (1.2.2)
+    i18n (1.14.1)
+      concurrent-ruby (~> 1.0)
+    minitest (5.20.0)
+    rrule (0.4.4)
+      activesupport (>= 2.3)
+    tzinfo (2.0.6)
+      concurrent-ruby (~> 1.0)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  rrule (= 0.4.4)
+
+BUNDLED WITH
+   2.4.13
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/default.nix
new file mode 100644
index 000000000000..7a6bd7f69270
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/default.nix
@@ -0,0 +1,18 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-calendar";
+  bundlerEnvArgs.gemdir = ./.;
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-calendar";
+    rev = "afc2ee684de41601d6cecc46713d139760f176a6";
+    sha256 = "sha256-rTQWO+E/Jg4zjZDYDvBrDQsox5q4dHkdQjwnJxgv3dI=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-calendar";
+    maintainers = with maintainers; [ ryantm ];
+    license = licenses.mit;
+    description = "Adds the ability to create a dynamic calendar in the first post of a topic";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/gemset.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/gemset.nix
new file mode 100644
index 000000000000..2e9b15ee5b9e
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-calendar/gemset.nix
@@ -0,0 +1,66 @@
+{
+  activesupport = {
+    dependencies = ["concurrent-ruby" "i18n" "minitest" "tzinfo"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "188kbwkn1lbhz40ala8ykp20jzqphgc68g3d8flin8cqa2xid0s5";
+      type = "gem";
+    };
+    version = "7.0.8";
+  };
+  concurrent-ruby = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0krcwb6mn0iklajwngwsg850nk8k9b35dhmc2qkbdqvmifdi2y9q";
+      type = "gem";
+    };
+    version = "1.2.2";
+  };
+  i18n = {
+    dependencies = ["concurrent-ruby"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0qaamqsh5f3szhcakkak8ikxlzxqnv49n2p7504hcz2l0f4nj0wx";
+      type = "gem";
+    };
+    version = "1.14.1";
+  };
+  minitest = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0bkmfi9mb49m0fkdhl2g38i3xxa02d411gg0m8x0gvbwfmmg5ym3";
+      type = "gem";
+    };
+    version = "5.20.0";
+  };
+  rrule = {
+    dependencies = ["activesupport"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "04h3q0ws0wswqj3mwjyv44yx59d9ima9a820ay9w5bwnlb73syj2";
+      type = "gem";
+    };
+    version = "0.4.4";
+  };
+  tzinfo = {
+    dependencies = ["concurrent-ruby"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "16w2g84dzaf3z13gxyzlzbf748kylk5bdgg3n1ipvkvvqy685bwd";
+      type = "gem";
+    };
+    version = "2.0.6";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-canned-replies/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-canned-replies/default.nix
new file mode 100644
index 000000000000..d5628fed4003
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-canned-replies/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-canned-replies";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-canned-replies";
+    rev = "732598b6cdc86c74622bb15bfeaebb05611bbc25";
+    sha256 = "sha256-t0emNsPT8o0ralUedt33ufH0VLl4/12lVBBCnzfdRxE=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-canned-replies";
+    maintainers = with maintainers; [ talyz ];
+    license = licenses.gpl2Only;
+    description = "Adds support for inserting a canned reply into the composer window via a UI";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-chat-integration/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-chat-integration/default.nix
new file mode 100644
index 000000000000..499d2e6447bd
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-chat-integration/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-chat-integration";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-chat-integration";
+    rev = "70fea6b66b68868aa4c00b45a169436deaa142a8";
+    sha256 = "sha256-K9MmP1F0B6Na2dTqgnsjMbTQFkF+nNKkI8aF3zPAodc=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-chat-integration";
+    maintainers = with maintainers; [ dpausp ];
+    license = licenses.mit;
+    description = "This plugin integrates Discourse with a number of external chatroom systems";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-checklist/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-checklist/default.nix
new file mode 100644
index 000000000000..f3fdd5459432
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-checklist/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-checklist";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-checklist";
+    rev = "d94e58c3060ee7ca0fe76339215ed9456d5f4ea4";
+    sha256 = "sha256-zTMkU8NRqxLQ3/ghYTmEhRqbCgdYsYaImHdGu7WwuFk=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-checklist";
+    maintainers = with maintainers; [ ryantm ];
+    license = licenses.gpl2Only;
+    description = "A simple checklist rendering plugin for discourse ";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-data-explorer/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-data-explorer/default.nix
new file mode 100644
index 000000000000..39320637ddcd
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-data-explorer/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-data-explorer";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-data-explorer";
+    rev = "e4f8d3924a18b303c2bb7da9472cf0c060060e4e";
+    sha256 = "sha256-K+GPszO3je6NmnhIRSqSEhylUK5oEByaS0bLfAGjvB4=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-data-explorer";
+    maintainers = with maintainers; [ ryantm ];
+    license = licenses.mit;
+    description = "SQL Queries for admins in Discourse";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-docs/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-docs/default.nix
new file mode 100644
index 000000000000..3dcd2b86a969
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-docs/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-docs";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-docs";
+    rev = "a4b203274b88c5277d0b5b936de0bc0e0016726c";
+    sha256 = "sha256-R+VP/gsb2Oa6lPVMhRoGZzOBx5C7kRSxqwYpWE10GHw=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-docs";
+    maintainers = with maintainers; [ dpausp ];
+    license = licenses.mit;
+    description = "Find and filter knowledge base topics";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/Gemfile b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/Gemfile
new file mode 100644
index 000000000000..c24a3e860d7c
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/Gemfile
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+# gem "rails"
+gem "sawyer", "0.9.2"
+gem "octokit", "5.6.1"
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/Gemfile.lock b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/Gemfile.lock
new file mode 100644
index 000000000000..3640cbc601da
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/Gemfile.lock
@@ -0,0 +1,27 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    addressable (2.8.5)
+      public_suffix (>= 2.0.2, < 6.0)
+    faraday (2.7.10)
+      faraday-net_http (>= 2.0, < 3.1)
+      ruby2_keywords (>= 0.0.4)
+    faraday-net_http (3.0.2)
+    octokit (5.6.1)
+      faraday (>= 1, < 3)
+      sawyer (~> 0.9)
+    public_suffix (5.0.3)
+    ruby2_keywords (0.0.5)
+    sawyer (0.9.2)
+      addressable (>= 2.3.5)
+      faraday (>= 0.17.3, < 3)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  octokit (= 5.6.1)
+  sawyer (= 0.9.2)
+
+BUNDLED WITH
+   2.4.13
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/default.nix
new file mode 100644
index 000000000000..50a59136ecf5
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/default.nix
@@ -0,0 +1,19 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-github";
+  bundlerEnvArgs.gemdir = ./.;
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-github";
+    rev = "8aa068d56ef010cecaabd50657e7753f4bbecc1f";
+    sha256 = "sha256-WzljuGvv6pki3ROkvhXZWQaq5D9JkCbWjdlkdRI8lHE=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-github";
+    maintainers = with maintainers; [ talyz ];
+    license = licenses.mit;
+    description = "Adds GitHub badges and linkback functionality";
+  };
+
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/gemset.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/gemset.nix
new file mode 100644
index 000000000000..87599999d894
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-github/gemset.nix
@@ -0,0 +1,76 @@
+{
+  addressable = {
+    dependencies = ["public_suffix"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "05r1fwy487klqkya7vzia8hnklcxy4vr92m9dmni3prfwk6zpw33";
+      type = "gem";
+    };
+    version = "2.8.5";
+  };
+  faraday = {
+    dependencies = ["faraday-net_http" "ruby2_keywords"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "187clqhp9mv5mnqmjlfdp57svhsg1bggz84ak8v333j9skrnrgh9";
+      type = "gem";
+    };
+    version = "2.7.10";
+  };
+  faraday-net_http = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "13byv3mp1gsjyv8k0ih4612y6vw5kqva6i03wcg4w2fqpsd950k8";
+      type = "gem";
+    };
+    version = "3.0.2";
+  };
+  octokit = {
+    dependencies = ["faraday" "sawyer"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "15g4kyag6gmxxq6d03472h7srm3imlsks1wg6nac7hl3mb1b5vs8";
+      type = "gem";
+    };
+    version = "5.6.1";
+  };
+  public_suffix = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0n9j7mczl15r3kwqrah09cxj8hxdfawiqxa60kga2bmxl9flfz9k";
+      type = "gem";
+    };
+    version = "5.0.3";
+  };
+  ruby2_keywords = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1vz322p8n39hz3b4a9gkmz9y7a5jaz41zrm2ywf31dvkqm03glgz";
+      type = "gem";
+    };
+    version = "0.0.5";
+  };
+  sawyer = {
+    dependencies = ["addressable" "faraday"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1jks1qjbmqm8f9kvwa81vqj39avaj9wdnzc531xm29a55bb74fps";
+      type = "gem";
+    };
+    version = "0.9.2";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/Gemfile b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/Gemfile
new file mode 100644
index 000000000000..e140770e4e6a
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/Gemfile
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+# gem "rails"
+gem 'pyu-ruby-sasl', '0.0.3.3', require: false
+gem 'rubyntlm', '0.3.4', require: false
+gem 'net-ldap', '0.17.1'
+gem 'omniauth-ldap', '1.0.5'
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/Gemfile.lock b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/Gemfile.lock
new file mode 100644
index 000000000000..f131626f7c45
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/Gemfile.lock
@@ -0,0 +1,28 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    hashie (5.0.0)
+    net-ldap (0.17.1)
+    omniauth (1.9.2)
+      hashie (>= 3.4.6)
+      rack (>= 1.6.2, < 3)
+    omniauth-ldap (1.0.5)
+      net-ldap (~> 0.12)
+      omniauth (~> 1.0)
+      pyu-ruby-sasl (~> 0.0.3.2)
+      rubyntlm (~> 0.3.4)
+    pyu-ruby-sasl (0.0.3.3)
+    rack (2.2.7)
+    rubyntlm (0.3.4)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  net-ldap (= 0.17.1)
+  omniauth-ldap (= 1.0.5)
+  pyu-ruby-sasl (= 0.0.3.3)
+  rubyntlm (= 0.3.4)
+
+BUNDLED WITH
+   2.4.10
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/default.nix
new file mode 100644
index 000000000000..82f13f0d0d8a
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/default.nix
@@ -0,0 +1,18 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-ldap-auth";
+  bundlerEnvArgs.gemdir = ./.;
+  src = fetchFromGitHub {
+    owner = "jonmbake";
+    repo = "discourse-ldap-auth";
+    rev = "edcf06957090e8d978a89fe7b07a6ba56fe35214";
+    sha256 = "sha256-VxBBip8QEXDQGDOsU5cXjUZe2HThJn20BPsNr33KhKI=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/jonmbake/discourse-ldap-auth";
+    maintainers = with maintainers; [ ryantm ];
+    license = licenses.mit;
+    description = "Discourse plugin to enable LDAP/Active Directory authentication.";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/gemset.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/gemset.nix
new file mode 100644
index 000000000000..9df3292f7b82
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-ldap-auth/gemset.nix
@@ -0,0 +1,74 @@
+{
+  hashie = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1nh3arcrbz1rc1cr59qm53sdhqm137b258y8rcb4cvd3y98lwv4x";
+      type = "gem";
+    };
+    version = "5.0.0";
+  };
+  net-ldap = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1ycw0qsw3hap8svakl0i30jkj0ffd4lpyrn17a1j0w8mz5ainmsj";
+      type = "gem";
+    };
+    version = "0.17.1";
+  };
+  omniauth = {
+    dependencies = ["hashie" "rack"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1jn9j54l5h7xcba2vjq74l1dk0xrwvsjxam4qhylpi52nw0h5502";
+      type = "gem";
+    };
+    version = "1.9.2";
+  };
+  omniauth-ldap = {
+    dependencies = ["net-ldap" "omniauth" "pyu-ruby-sasl" "rubyntlm"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1ld3mx46xa1qhc0cpnck1n06xcxs0ag4n41zgabxri27a772f9wz";
+      type = "gem";
+    };
+    version = "1.0.5";
+  };
+  pyu-ruby-sasl = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1rcpjiz9lrvyb3rd8k8qni0v4ps08psympffyldmmnrqayyad0sn";
+      type = "gem";
+    };
+    version = "0.0.3.3";
+  };
+  rack = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "16w217k9z02c4hqizym8dkj6bqmmzx4qdvqpnskgzf174a5pwdxk";
+      type = "gem";
+    };
+    version = "2.2.7";
+  };
+  rubyntlm = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "18d1lxhx62swggf4cqg76h7hp04f5801c8h07w08cm9xng2niqby";
+      type = "gem";
+    };
+    version = "0.3.4";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-math/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-math/default.nix
new file mode 100644
index 000000000000..3a07b4bfd342
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-math/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-math";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-math";
+    rev = "529ad1fe6da924da378a60bec48c35657bb01a68";
+    sha256 = "sha256-zhtAy0tTVMzQfPilTwfyyzxgCJD4xazOITBuliFR5Gg=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-math";
+    maintainers = with maintainers; [ talyz ];
+    license = licenses.mit;
+    description = "Official MathJax support for Discourse";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/Gemfile b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/Gemfile
new file mode 100644
index 000000000000..59c64586dc17
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/Gemfile
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+# gem "rails"
+gem 'bcrypt', '3.1.13'
+gem 'unix-crypt', '1.3.0'
+gem 'ffi', '1.15.5', require: false
+gem 'ffi-compiler', '1.0.1', require: false
+gem 'argon2', '2.2.0'
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/Gemfile.lock b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/Gemfile.lock
new file mode 100644
index 000000000000..75a9a363b6cc
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/Gemfile.lock
@@ -0,0 +1,26 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    argon2 (2.2.0)
+      ffi (~> 1.15)
+      ffi-compiler (~> 1.0)
+    bcrypt (3.1.13)
+    ffi (1.15.5)
+    ffi-compiler (1.0.1)
+      ffi (>= 1.0.0)
+      rake
+    rake (13.0.6)
+    unix-crypt (1.3.0)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  argon2 (= 2.2.0)
+  bcrypt (= 3.1.13)
+  ffi (= 1.15.5)
+  ffi-compiler (= 1.0.1)
+  unix-crypt (= 1.3.0)
+
+BUNDLED WITH
+   2.4.13
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/default.nix
new file mode 100644
index 000000000000..ee8d03e66ca8
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/default.nix
@@ -0,0 +1,18 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-migratepassword";
+  bundlerEnvArgs.gemdir = ./.;
+  src = fetchFromGitHub {
+    owner = "communiteq";
+    repo = "discourse-migratepassword";
+    rev = "a95ae6bca4126172186fafcd2315f51a4504c23b";
+    sha256 = "sha256-lr2xHz+8q4XnHc/7KLX0Z2m0KMffLgGYk36zxGG9X5o=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/communiteq/discourse-migratepassword";
+    maintainers = with maintainers; [ ryantm ];
+    license = licenses.gpl2Only;
+    description = "Support migrated password hashes";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/gemset.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/gemset.nix
new file mode 100644
index 000000000000..97aa9bfc7048
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-migratepassword/gemset.nix
@@ -0,0 +1,64 @@
+{
+  argon2 = {
+    dependencies = ["ffi" "ffi-compiler"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1wdllcqlr81nzyf485ldv1p660xsi476p79ghbj7zsf3n9n86gwd";
+      type = "gem";
+    };
+    version = "2.2.0";
+  };
+  bcrypt = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0ai0m15jg3n0b22mimk09ppnga316dc7dyvz06w8rrqh5gy1lslp";
+      type = "gem";
+    };
+    version = "3.1.13";
+  };
+  ffi = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1862ydmclzy1a0cjbvm8dz7847d9rch495ib0zb64y84d3xd4bkg";
+      type = "gem";
+    };
+    version = "1.15.5";
+  };
+  ffi-compiler = {
+    dependencies = ["ffi" "rake"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0c2caqm9wqnbidcb8dj4wd3s902z15qmgxplwyfyqbwa0ydki7q1";
+      type = "gem";
+    };
+    version = "1.0.1";
+  };
+  rake = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "15whn7p9nrkxangbs9hh75q585yfn66lv0v2mhj6q6dl6x8bzr2w";
+      type = "gem";
+    };
+    version = "13.0.6";
+  };
+  unix-crypt = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1wflipsmmicmgvqilp9pml4x19b337kh6p6jgrzqrzpkq2z52gdq";
+      type = "gem";
+    };
+    version = "1.3.0";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/Gemfile b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/Gemfile
new file mode 100644
index 000000000000..7da32ec03949
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/Gemfile
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
+
+group :development do
+  gem 'rubocop-discourse'
+end
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/Gemfile.lock b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/Gemfile.lock
new file mode 100644
index 000000000000..6a91a08c0e86
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/Gemfile.lock
@@ -0,0 +1,37 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    ast (2.4.2)
+    parallel (1.22.1)
+    parser (3.1.1.0)
+      ast (~> 2.4.1)
+    rainbow (3.1.1)
+    regexp_parser (2.2.1)
+    rexml (3.2.5)
+    rubocop (1.26.1)
+      parallel (~> 1.10)
+      parser (>= 3.1.0.0)
+      rainbow (>= 2.2.2, < 4.0)
+      regexp_parser (>= 1.8, < 3.0)
+      rexml
+      rubocop-ast (>= 1.16.0, < 2.0)
+      ruby-progressbar (~> 1.7)
+      unicode-display_width (>= 1.4.0, < 3.0)
+    rubocop-ast (1.16.0)
+      parser (>= 3.1.1.0)
+    rubocop-discourse (2.5.0)
+      rubocop (>= 1.1.0)
+      rubocop-rspec (>= 2.0.0)
+    rubocop-rspec (2.9.0)
+      rubocop (~> 1.19)
+    ruby-progressbar (1.11.0)
+    unicode-display_width (2.1.0)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  rubocop-discourse
+
+BUNDLED WITH
+   2.1.4
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/default.nix
new file mode 100644
index 000000000000..a013383d1a2f
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/default.nix
@@ -0,0 +1,18 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin rec {
+  name = "discourse-oauth2-basic";
+  bundlerEnvArgs.gemdir = ./.;
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = name;
+    rev = "06ba5daa9aabd0487f2f30b944b6500f1f481308";
+    sha256 = "sha256-T08Q36k2hb9wVimKIa4O5mWcrr6VBTfHvhRJiLBiRPY=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/${name}";
+    maintainers = with maintainers; [ ehmry ];
+    license = licenses.mit;
+    description = "A basic OAuth2 plugin for use with Discourse";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/gemset.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/gemset.nix
new file mode 100644
index 000000000000..bbb35327787b
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-oauth2-basic/gemset.nix
@@ -0,0 +1,127 @@
+{
+  ast = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "04nc8x27hlzlrr5c2gn7mar4vdr0apw5xg22wp6m8dx3wqr04a0y";
+      type = "gem";
+    };
+    version = "2.4.2";
+  };
+  parallel = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "07vnk6bb54k4yc06xnwck7php50l09vvlw1ga8wdz0pia461zpzb";
+      type = "gem";
+    };
+    version = "1.22.1";
+  };
+  parser = {
+    dependencies = ["ast"];
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0zaghgvva2q4jqbachg8jvpwgbg3w1jqr0d00m8rqciqznjgsw3c";
+      type = "gem";
+    };
+    version = "3.1.1.0";
+  };
+  rainbow = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0smwg4mii0fm38pyb5fddbmrdpifwv22zv3d3px2xx497am93503";
+      type = "gem";
+    };
+    version = "3.1.1";
+  };
+  regexp_parser = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "155f6cr4rrfw5bs5xd3m5kfw32qhc5fsi4nk82rhif56rc6cs0wm";
+      type = "gem";
+    };
+    version = "2.2.1";
+  };
+  rexml = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "08ximcyfjy94pm1rhcx04ny1vx2sk0x4y185gzn86yfsbzwkng53";
+      type = "gem";
+    };
+    version = "3.2.5";
+  };
+  rubocop = {
+    dependencies = ["parallel" "parser" "rainbow" "regexp_parser" "rexml" "rubocop-ast" "ruby-progressbar" "unicode-display_width"];
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "06105yrqajpm5l07fng1nbk55y9490hny542zclnan8hg841pjgl";
+      type = "gem";
+    };
+    version = "1.26.1";
+  };
+  rubocop-ast = {
+    dependencies = ["parser"];
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1bd2z82ly7fix8415gvfiwzb6bjialz5rs3sr72kv1lk68rd23wv";
+      type = "gem";
+    };
+    version = "1.16.0";
+  };
+  rubocop-discourse = {
+    dependencies = ["rubocop" "rubocop-rspec"];
+    groups = ["development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "01f4y7am9cq276zl8vsgv64w8wfmhpbzg7vzsifhgnnh92g6s04g";
+      type = "gem";
+    };
+    version = "2.5.0";
+  };
+  rubocop-rspec = {
+    dependencies = ["rubocop"];
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "051gq9pz49iv4gq34d3n089iaa6cb418n2fhin6gd6fpysbi3nf6";
+      type = "gem";
+    };
+    version = "2.9.0";
+  };
+  ruby-progressbar = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "02nmaw7yx9kl7rbaan5pl8x5nn0y4j5954mzrkzi9i3dhsrps4nc";
+      type = "gem";
+    };
+    version = "1.11.0";
+  };
+  unicode-display_width = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0csjm9shhfik0ci9mgimb7hf3xgh7nx45rkd9rzgdz6vkwr8rzxn";
+      type = "gem";
+    };
+    version = "2.1.0";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/Gemfile b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/Gemfile
new file mode 100644
index 000000000000..7da32ec03949
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/Gemfile
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
+
+group :development do
+  gem 'rubocop-discourse'
+end
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/Gemfile.lock b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/Gemfile.lock
new file mode 100644
index 000000000000..0987b206fa66
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/Gemfile.lock
@@ -0,0 +1,37 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    ast (2.4.1)
+    parallel (1.19.2)
+    parser (2.7.2.0)
+      ast (~> 2.4.1)
+    rainbow (3.0.0)
+    regexp_parser (1.8.1)
+    rexml (3.2.5)
+    rubocop (0.93.0)
+      parallel (~> 1.10)
+      parser (>= 2.7.1.5)
+      rainbow (>= 2.2.2, < 4.0)
+      regexp_parser (>= 1.8)
+      rexml
+      rubocop-ast (>= 0.6.0)
+      ruby-progressbar (~> 1.7)
+      unicode-display_width (>= 1.4.0, < 2.0)
+    rubocop-ast (0.7.1)
+      parser (>= 2.7.1.5)
+    rubocop-discourse (2.3.2)
+      rubocop (>= 0.69.0)
+      rubocop-rspec (>= 1.39.0)
+    rubocop-rspec (1.43.2)
+      rubocop (~> 0.87)
+    ruby-progressbar (1.10.1)
+    unicode-display_width (1.7.0)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  rubocop-discourse
+
+BUNDLED WITH
+   2.1.4
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/default.nix
new file mode 100644
index 000000000000..a467f4d17b39
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/default.nix
@@ -0,0 +1,19 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-openid-connect";
+  bundlerEnvArgs.gemdir = ./.;
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-openid-connect";
+    rev = "b1df541ad29f6f6098a1008b83393b2d400986ed";
+    sha256 = "sha256-afRd/9M0nQGkS14Q8BJhcJwMCkOku3Fr0uHxcRl44vQ=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-openid-connect";
+    maintainers = with maintainers; [ mkg20001 ];
+    license = licenses.mit;
+    description = "Discourse plugin to integrate Discourse with an openid-connect login provider.";
+  };
+}
+
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/gemset.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/gemset.nix
new file mode 100644
index 000000000000..2a546e7a1c87
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-openid-connect/gemset.nix
@@ -0,0 +1,127 @@
+{
+  ast = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1l3468czzjmxl93ap40hp7z94yxp4nbag0bxqs789bm30md90m2a";
+      type = "gem";
+    };
+    version = "2.4.1";
+  };
+  parallel = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "17b127xxmm2yqdz146qwbs57046kn0js1h8synv01dwqz2z1kp2l";
+      type = "gem";
+    };
+    version = "1.19.2";
+  };
+  parser = {
+    dependencies = ["ast"];
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1f7gmm60yla325wlnd3qkxs59qm2y0aan8ljpg6k18rwzrrfil6z";
+      type = "gem";
+    };
+    version = "2.7.2.0";
+  };
+  rainbow = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0bb2fpjspydr6x0s8pn1pqkzmxszvkfapv0p4627mywl7ky4zkhk";
+      type = "gem";
+    };
+    version = "3.0.0";
+  };
+  regexp_parser = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0n9d14ppshnx71i3mi1pnm3hwhcbb6m6vsc0b0dqgsab8r2rs96n";
+      type = "gem";
+    };
+    version = "1.8.1";
+  };
+  rexml = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "08ximcyfjy94pm1rhcx04ny1vx2sk0x4y185gzn86yfsbzwkng53";
+      type = "gem";
+    };
+    version = "3.2.5";
+  };
+  rubocop = {
+    dependencies = ["parallel" "parser" "rainbow" "regexp_parser" "rexml" "rubocop-ast" "ruby-progressbar" "unicode-display_width"];
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1nrv7i81549addig09grw17qkab3l4319dcsf9y7psl7aa76ng3a";
+      type = "gem";
+    };
+    version = "0.93.0";
+  };
+  rubocop-ast = {
+    dependencies = ["parser"];
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "129hgz4swc8n0g01715v7y00k0h4mlzkxh63q7z27q7mjp54rl74";
+      type = "gem";
+    };
+    version = "0.7.1";
+  };
+  rubocop-discourse = {
+    dependencies = ["rubocop" "rubocop-rspec"];
+    groups = ["development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "10l2wwnvd4xccgqsyhxrhc5bw10b7an4awl0v90fw5xf2qdjiflw";
+      type = "gem";
+    };
+    version = "2.3.2";
+  };
+  rubocop-rspec = {
+    dependencies = ["rubocop"];
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1sc0bwdxzfr8byxzwvfyf22lwzqcaa6ca7wzxx31mk7vvy7r7dhl";
+      type = "gem";
+    };
+    version = "1.43.2";
+  };
+  ruby-progressbar = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1k77i0d4wsn23ggdd2msrcwfy0i376cglfqypkk2q77r2l3408zf";
+      type = "gem";
+    };
+    version = "1.10.1";
+  };
+  unicode-display_width = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "06i3id27s60141x6fdnjn5rar1cywdwy64ilc59cz937303q3mna";
+      type = "gem";
+    };
+    version = "1.7.0";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/Gemfile b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/Gemfile
new file mode 100644
index 000000000000..54a39883d060
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/Gemfile
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+# gem "rails"
+gem "webrick", "1.7.0"
+gem "prometheus_exporter", "2.0.6"
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/Gemfile.lock b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/Gemfile.lock
new file mode 100644
index 000000000000..88a3a3c8d654
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/Gemfile.lock
@@ -0,0 +1,16 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    prometheus_exporter (2.0.6)
+      webrick
+    webrick (1.7.0)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  prometheus_exporter (= 2.0.6)
+  webrick (= 1.7.0)
+
+BUNDLED WITH
+   2.4.13
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/default.nix
new file mode 100644
index 000000000000..95bf4c5a679a
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/default.nix
@@ -0,0 +1,26 @@
+{ lib, stdenv, mkDiscoursePlugin, fetchFromGitHub }:
+
+ mkDiscoursePlugin {
+  bundlerEnvArgs.gemdir = ./.;
+  name = "discourse-prometheus";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-prometheus";
+    rev = "8a7a46a80cc65aa0839bc5e3c3b6f8ef6544089f";
+    sha256 = "sha256-TL+pbP26LvRMKdy8CAuBEK+LZfAs8HfggMeUDaBu9hc=";
+  };
+
+  patches = [
+    # The metrics collector tries to run git to get the commit id but fails
+    # because we don't run Discourse from a Git repository.
+    ./no-git-version.patch
+    ./spec-import-fix-abi-version.patch
+  ];
+
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-prometheus";
+    maintainers = with maintainers; [ dpausp ];
+    license = licenses.mit;
+    description = "Official Discourse Plugin for Prometheus Monitoring";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/gemset.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/gemset.nix
new file mode 100644
index 000000000000..b6f3158174c1
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/gemset.nix
@@ -0,0 +1,23 @@
+{
+  prometheus_exporter = {
+    dependencies = ["webrick"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0pb4k6px8b36bvnw3d14j31s33ns60dcwxixbcgvhpzavd7fparb";
+      type = "gem";
+    };
+    version = "2.0.6";
+  };
+  webrick = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1d4cvgmxhfczxiq5fr534lmizkhigd15bsx5719r5ds7k7ivisc7";
+      type = "gem";
+    };
+    version = "1.7.0";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/no-git-version.patch b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/no-git-version.patch
new file mode 100644
index 000000000000..9aebfd8aa794
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/no-git-version.patch
@@ -0,0 +1,34 @@
+diff --git a/lib/internal_metric/global.rb b/lib/internal_metric/global.rb
+index 682571b..7bdd431 100644
+--- a/lib/internal_metric/global.rb
++++ b/lib/internal_metric/global.rb
+@@ -30,28 +30,7 @@ module DiscoursePrometheus::InternalMetric
+       @active_app_reqs = 0
+       @queued_app_reqs = 0
+       @fault_logged = {}
+-
+-      begin
+-        @@version = nil
+-
+-        out, error, status = Open3.capture3("git rev-parse HEAD")
+-
+-        if status.success?
+-          @@version ||= out.chomp
+-        else
+-          raise error
+-        end
+-      rescue => e
+-        if defined?(::Discourse)
+-          Discourse.warn_exception(e, message: "Failed to calculate discourse_version_info metric")
+-        else
+-          STDERR.puts "Failed to calculate discourse_version_info metric: #{e}\n#{e.backtrace.join("\n")}"
+-        end
+-
+-        @@retries ||= 10
+-        @@retries -= 1
+-        @@version = -1 if @@retries < 0
+-      end
++      @@version = -1
+     end
+ 
+     def collect
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/prometheus_exporter_version b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/prometheus_exporter_version
new file mode 100644
index 000000000000..157e54f3e4d5
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/prometheus_exporter_version
@@ -0,0 +1 @@
+2.0.6
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/spec-import-fix-abi-version.patch b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/spec-import-fix-abi-version.patch
new file mode 100644
index 000000000000..de3a5c718f00
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-prometheus/spec-import-fix-abi-version.patch
@@ -0,0 +1,20 @@
+diff --git a/bin/collector b/bin/collector
+index 6bd04a8caffb..119526fc6ea3 100644
+--- a/bin/collector
++++ b/bin/collector
+@@ -3,12 +3,14 @@
+ 
+ Process.setproctitle("discourse prometheus-collector")
+ 
++# We need the ABI version {MAJOR}.{MINOR}.0 here.
++abi_version = ENV['GEM_PATH'].split("/")[-1]
+ [
+   "webrick-#{ENV["WEBRICK_VERSION"]}",
+   "prometheus_exporter-#{ENV["PROMETHEUS_EXPORTER_VERSION"]}",
+ ].each do |spec_name|
+   spec_file =
+-    File.expand_path("../../gems/#{RUBY_VERSION}/specifications/#{spec_name}.gemspec", __FILE__)
++    File.expand_path("../../gems/#{abi_version}/specifications/#{spec_name}.gemspec", __FILE__)
+   spec = Gem::Specification.load(spec_file)
+   spec.activate
+ end
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-reactions/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-reactions/default.nix
new file mode 100644
index 000000000000..36e4ac19c4bd
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-reactions/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-reactions";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-reactions";
+    rev = "643f807a3a2195f08211064301f0350d9f51604f";
+    sha256 = "sha256-4FdiYUNysSuOJ664G3YvlUHx/J7MLUS3kVBdXT47oEw=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-reactions";
+    maintainers = with maintainers; [ bbenno ];
+    license = licenses.mit;
+    description = "Allows users to react to a post from a choice of emojis, rather than only the like heart";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-saved-searches/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-saved-searches/default.nix
new file mode 100644
index 000000000000..32709666189e
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-saved-searches/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-saved-searches";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-saved-searches";
+    rev = "7c9bdcd68951e7cef16cafe3c4bfb583bb994d2a";
+    sha256 = "sha256-6RIN12ACDCeRcxmsC3FgeIPdvovI4arn7w/Dqil1yCI=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-saved-searches";
+    maintainers = with maintainers; [ dpausp ];
+    license = licenses.mit;
+    description = "Allow users to save searches and be notified of new results";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-solved/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-solved/default.nix
new file mode 100644
index 000000000000..ed47f9e15e92
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-solved/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-solved";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-solved";
+    rev = "b5d487d6a5bfe2571d936eec5911d02a5f3fcc32";
+    sha256 = "sha256-Tt7B9PcsV8E7B+m8GnJw+MBz9rGYtojKt6NjBFMQvOM=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-solved";
+    maintainers = with maintainers; [ talyz ];
+    license = licenses.mit;
+    description = "Allow accepted answers on topics";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-spoiler-alert/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-spoiler-alert/default.nix
new file mode 100644
index 000000000000..23ce34dcd694
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-spoiler-alert/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-spoiler-alert";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-spoiler-alert";
+    rev = "65989714af08eda44196cca3a0afe85c9e9443f9";
+    sha256 = "sha256-R/vqNEDst50+Y7anckIvhy4viBOqBemIZMh4sPt7kRM=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-spoiler-alert";
+    maintainers = with maintainers; [ talyz ];
+    license = licenses.mit;
+    description = "Hide spoilers behind the spoiler-alert jQuery plugin";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-voting/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-voting/default.nix
new file mode 100644
index 000000000000..a311dbcfbfcf
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-voting/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-voting";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-voting";
+    rev = "6449fc15658d972e20086a3f1fae3dbac9cd9eeb";
+    sha256 = "sha256-f04LpVeodCVEB/t5Ic2dketp542Nrc0rZWbQ6hrC22g=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-voting";
+    maintainers = with maintainers; [ dpausp ];
+    license = licenses.gpl2Only;
+    description = "Adds the ability for voting on a topic within a specified category in Discourse";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-yearly-review/default.nix b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-yearly-review/default.nix
new file mode 100644
index 000000000000..979398f7394b
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/plugins/discourse-yearly-review/default.nix
@@ -0,0 +1,17 @@
+{ lib, mkDiscoursePlugin, fetchFromGitHub }:
+
+mkDiscoursePlugin {
+  name = "discourse-yearly-review";
+  src = fetchFromGitHub {
+    owner = "discourse";
+    repo = "discourse-yearly-review";
+    rev = "3246c6b378f9e69e664c575efc63c2ad83bcac2f";
+    sha256 = "sha256-usHHyfYP4YAQ94f7gvNSH7VBRRkdZMmsSi9QQM8tPfY=";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/discourse/discourse-yearly-review";
+    maintainers = with maintainers; [ talyz ];
+    license = licenses.mit;
+    description = "Publishes an automated Year in Review topic";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/Gemfile b/nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/Gemfile
new file mode 100644
index 000000000000..647aefea8ada
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/Gemfile
@@ -0,0 +1,278 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+# if there is a super emergency and rubygems is playing up, try
+#source 'http://production.cf.rubygems.org'
+
+gem "bootsnap", require: false, platform: :mri
+
+def rails_master?
+  ENV["RAILS_MASTER"] == "1"
+end
+
+if rails_master?
+  gem "arel", git: "https://github.com/rails/arel.git"
+  gem "rails", git: "https://github.com/rails/rails.git"
+else
+  # NOTE: Until rubygems gives us optional dependencies we are stuck with this needing to be explicit
+  # this allows us to include the bits of rails we use without pieces we do not.
+  #
+  # To issue a rails update bump the version number here
+  rails_version = "7.0.5.1"
+  gem "actionmailer", rails_version
+  gem "actionpack", rails_version
+  gem "actionview", rails_version
+  gem "activemodel", rails_version
+  gem "activerecord", rails_version
+  gem "activesupport", rails_version
+  gem "railties", rails_version
+  gem "sprockets-rails"
+end
+
+gem "json"
+
+# TODO: At the moment Discourse does not work with Sprockets 4, we would need to correct internals
+# We intend to drop sprockets rather than upgrade to 4.x
+gem "sprockets", git: "https://github.com/rails/sprockets", branch: "3.x"
+
+# this will eventually be added to rails,
+# allows us to precompile all our templates in the unicorn master
+gem "actionview_precompiler", require: false
+
+gem "discourse-seed-fu"
+
+gem "mail"
+gem "mini_mime"
+gem "mini_suffix"
+
+gem "redis"
+
+# This is explicitly used by Sidekiq and is an optional dependency.
+# We tell Sidekiq to use the namespace "sidekiq" which triggers this
+# gem to be used. There is no explicit dependency in sidekiq cause
+# redis namespace support is optional
+# We already namespace stuff in DiscourseRedis, so we should consider
+# just using a single implementation in core vs having 2 namespace implementations
+gem "redis-namespace"
+
+# NOTE: AM serializer gets a lot slower with recent updates
+# we used an old branch which is the fastest one out there
+# are long term goal here is to fork this gem so we have a
+# better maintained living fork
+gem "active_model_serializers", "~> 0.8.3"
+
+gem "http_accept_language", require: false
+
+gem "discourse-fonts", require: "discourse_fonts"
+
+gem "message_bus"
+
+gem "rails_multisite"
+
+gem "fast_xs", platform: :ruby
+
+gem "fastimage"
+
+gem "aws-sdk-s3", require: false
+gem "aws-sdk-sns", require: false
+gem "excon", require: false
+gem "unf", require: false
+
+gem "email_reply_trimmer"
+
+gem "image_optim"
+gem "multi_json"
+gem "mustache"
+gem "nokogiri"
+gem "loofah"
+gem "css_parser", require: false
+
+gem "omniauth"
+gem "omniauth-facebook"
+gem "omniauth-twitter"
+gem "omniauth-github"
+
+gem "omniauth-oauth2", require: false
+
+gem "omniauth-google-oauth2"
+
+gem "oj"
+
+gem "pg"
+gem "mini_sql"
+gem "pry-rails", require: false
+gem "pry-byebug", require: false
+gem "rtlcss", require: false
+gem "rake"
+
+gem "thor", require: false
+gem "diffy", require: false
+gem "rinku"
+gem "sidekiq"
+gem "mini_scheduler"
+
+gem "execjs", require: false
+gem "mini_racer"
+
+gem "highline", require: false
+
+gem "rack"
+
+gem "rack-protection" # security
+gem "cbor", require: false
+gem "cose", require: false
+gem "addressable"
+gem "json_schemer"
+
+gem "net-smtp", require: false
+gem "net-imap", require: false
+gem "net-pop", require: false
+gem "digest", require: false
+
+# Gems used only for assets and not required in production environments by default.
+# Allow everywhere for now cause we are allowing asset debugging in production
+group :assets do
+  gem "uglifier"
+end
+
+group :test do
+  gem "capybara", require: false
+  gem "webmock", require: false
+  gem "fakeweb", require: false
+  gem "minitest", require: false
+  gem "simplecov", require: false
+  gem "selenium-webdriver", require: false
+  gem "test-prof"
+  gem "webdrivers", require: false
+  gem "rails-dom-testing", require: false
+end
+
+group :test, :development do
+  gem "rspec"
+  gem "listen", require: false
+  gem "certified", require: false
+  gem "fabrication", require: false
+  gem "mocha", require: false
+
+  gem "rb-fsevent", require: RUBY_PLATFORM =~ /darwin/i ? "rb-fsevent" : false
+
+  gem "rspec-rails"
+
+  gem "shoulda-matchers", require: false, github: "thoughtbot/shoulda-matchers"
+  gem "rspec-html-matchers"
+  gem "byebug", require: ENV["RM_INFO"].nil?, platform: :mri
+  gem "rubocop-discourse", require: false
+  gem "parallel_tests"
+
+  gem "rswag-specs"
+
+  gem "annotate"
+
+  gem "syntax_tree"
+  gem "syntax_tree-disable_ternary"
+end
+
+group :development do
+  gem "ruby-prof", require: false, platform: :mri
+  gem "bullet", require: !!ENV["BULLET"]
+  gem "better_errors", platform: :mri, require: !!ENV["BETTER_ERRORS"]
+  gem "binding_of_caller"
+  gem "yaml-lint"
+  gem "yard"
+end
+
+if ENV["ALLOW_DEV_POPULATE"] == "1"
+  gem "discourse_dev_assets"
+  gem "faker", "~> 2.16"
+else
+  group :development, :test do
+    gem "discourse_dev_assets"
+    gem "faker", "~> 2.16"
+  end
+end
+
+# this is an optional gem, it provides a high performance replacement
+# to String#blank? a method that is called quite frequently in current
+# ActiveRecord, this may change in the future
+gem "fast_blank", platform: :ruby
+
+# this provides a very efficient lru cache
+gem "lru_redux"
+
+gem "htmlentities", require: false
+
+# IMPORTANT: mini profiler monkey patches, so it better be required last
+#  If you want to amend mini profiler to do the monkey patches in the railties
+#  we are open to it. by deferring require to the initializer we can configure discourse installs without it
+
+gem "rack-mini-profiler", require: ["enable_rails_patches"]
+
+gem "unicorn", require: false, platform: :ruby
+gem "puma", require: false
+gem "rbtrace", require: false, platform: :mri
+gem "gc_tracer", require: false, platform: :mri
+
+# required for feed importing and embedding
+gem "ruby-readability", require: false
+
+# rss gem is a bundled gem from Ruby 3 onwards
+gem "rss", require: false
+
+gem "stackprof", require: false, platform: :mri
+gem "memory_profiler", require: false, platform: :mri
+
+gem "cppjieba_rb", require: false
+
+gem "lograge", require: false
+gem "logstash-event", require: false
+gem "logstash-logger", require: false
+gem "logster"
+
+# These are forks of sassc and sassc-rails with dart-sass support
+gem "dartsass-ruby"
+gem "dartsass-sprockets"
+
+gem "rotp", require: false
+
+gem "rqrcode"
+
+gem "rubyzip", require: false
+
+gem "sshkey", require: false
+
+gem "rchardet", require: false
+gem "lz4-ruby", require: false, platform: :ruby
+
+gem "sanitize"
+
+if ENV["IMPORT"] == "1"
+  gem "mysql2"
+  gem "redcarpet"
+
+  # NOTE: in import mode the version of sqlite can matter a lot, so we stick it to a specific one
+  gem "sqlite3", "~> 1.3", ">= 1.3.13"
+  gem "ruby-bbcode-to-md", git: "https://github.com/nlalonde/ruby-bbcode-to-md"
+  gem "reverse_markdown"
+  gem "tiny_tds"
+  gem "csv"
+
+  gem "parallel", require: false
+end
+
+gem "web-push"
+gem "colored2", require: false
+gem "maxminddb"
+
+gem "rails_failover", require: false
+
+gem "faraday"
+gem "faraday-retry"
+
+# workaround for faraday-net_http, see
+# https://github.com/ruby/net-imap/issues/16#issuecomment-803086765
+gem "net-http"
+
+# Workaround until Ruby ships with cgi version 0.3.6 or higher.
+gem "cgi", ">= 0.3.6", require: false
+
+gem "tzinfo-data"
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/Gemfile.lock b/nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/Gemfile.lock
new file mode 100644
index 000000000000..0b93bf23d097
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/Gemfile.lock
@@ -0,0 +1,651 @@
+GIT
+  remote: https://github.com/rails/sprockets
+  revision: f4d3dae71ef29c44b75a49cfbf8032cce07b423a
+  branch: 3.x
+  specs:
+    sprockets (3.7.2)
+      concurrent-ruby (~> 1.0)
+      rack (> 1, < 3)
+
+GIT
+  remote: https://github.com/thoughtbot/shoulda-matchers.git
+  revision: 783a90554053002017510285bc736099b2749c22
+  specs:
+    shoulda-matchers (5.3.0)
+      activesupport (>= 5.2.0)
+
+GEM
+  remote: https://rubygems.org/
+  specs:
+    actionmailer (7.0.5.1)
+      actionpack (= 7.0.5.1)
+      actionview (= 7.0.5.1)
+      activejob (= 7.0.5.1)
+      activesupport (= 7.0.5.1)
+      mail (~> 2.5, >= 2.5.4)
+      net-imap
+      net-pop
+      net-smtp
+      rails-dom-testing (~> 2.0)
+    actionpack (7.0.5.1)
+      actionview (= 7.0.5.1)
+      activesupport (= 7.0.5.1)
+      rack (~> 2.0, >= 2.2.4)
+      rack-test (>= 0.6.3)
+      rails-dom-testing (~> 2.0)
+      rails-html-sanitizer (~> 1.0, >= 1.2.0)
+    actionview (7.0.5.1)
+      activesupport (= 7.0.5.1)
+      builder (~> 3.1)
+      erubi (~> 1.4)
+      rails-dom-testing (~> 2.0)
+      rails-html-sanitizer (~> 1.1, >= 1.2.0)
+    actionview_precompiler (0.2.3)
+      actionview (>= 6.0.a)
+    active_model_serializers (0.8.4)
+      activemodel (>= 3.0)
+    activejob (7.0.5.1)
+      activesupport (= 7.0.5.1)
+      globalid (>= 0.3.6)
+    activemodel (7.0.5.1)
+      activesupport (= 7.0.5.1)
+    activerecord (7.0.5.1)
+      activemodel (= 7.0.5.1)
+      activesupport (= 7.0.5.1)
+    activesupport (7.0.5.1)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 1.6, < 2)
+      minitest (>= 5.1)
+      tzinfo (~> 2.0)
+    addressable (2.8.4)
+      public_suffix (>= 2.0.2, < 6.0)
+    annotate (3.2.0)
+      activerecord (>= 3.2, < 8.0)
+      rake (>= 10.4, < 14.0)
+    ast (2.4.2)
+    aws-eventstream (1.2.0)
+    aws-partitions (1.583.0)
+    aws-sdk-core (3.130.2)
+      aws-eventstream (~> 1, >= 1.0.2)
+      aws-partitions (~> 1, >= 1.525.0)
+      aws-sigv4 (~> 1.1)
+      jmespath (~> 1.0)
+    aws-sdk-kms (1.56.0)
+      aws-sdk-core (~> 3, >= 3.127.0)
+      aws-sigv4 (~> 1.1)
+    aws-sdk-s3 (1.114.0)
+      aws-sdk-core (~> 3, >= 3.127.0)
+      aws-sdk-kms (~> 1)
+      aws-sigv4 (~> 1.4)
+    aws-sdk-sns (1.53.0)
+      aws-sdk-core (~> 3, >= 3.127.0)
+      aws-sigv4 (~> 1.1)
+    aws-sigv4 (1.5.0)
+      aws-eventstream (~> 1, >= 1.0.2)
+    better_errors (2.10.1)
+      erubi (>= 1.0.0)
+      rack (>= 0.9.0)
+      rouge (>= 1.0.0)
+    binding_of_caller (1.0.0)
+      debug_inspector (>= 0.0.1)
+    bootsnap (1.16.0)
+      msgpack (~> 1.2)
+    builder (3.2.4)
+    bullet (7.0.7)
+      activesupport (>= 3.0.0)
+      uniform_notifier (~> 1.11)
+    byebug (11.1.3)
+    capybara (3.39.2)
+      addressable
+      matrix
+      mini_mime (>= 0.1.3)
+      nokogiri (~> 1.8)
+      rack (>= 1.6.0)
+      rack-test (>= 0.6.3)
+      regexp_parser (>= 1.5, < 3.0)
+      xpath (~> 3.2)
+    cbor (0.5.9.6)
+    certified (1.0.0)
+    cgi (0.3.6)
+    chunky_png (1.4.0)
+    coderay (1.1.3)
+    colored2 (3.1.2)
+    concurrent-ruby (1.2.2)
+    connection_pool (2.4.1)
+    cose (1.3.0)
+      cbor (~> 0.5.9)
+      openssl-signature_algorithm (~> 1.0)
+    cppjieba_rb (0.4.2)
+    crack (0.4.5)
+      rexml
+    crass (1.0.6)
+    css_parser (1.14.0)
+      addressable
+    dartsass-ruby (3.0.1)
+      sass-embedded (~> 1.54)
+    dartsass-sprockets (3.0.0)
+      dartsass-ruby (~> 3.0)
+      railties (>= 4.0.0)
+      sprockets (> 3.0)
+      sprockets-rails
+      tilt
+    date (3.3.3)
+    debug_inspector (1.1.0)
+    diff-lcs (1.5.0)
+    diffy (3.4.2)
+    digest (3.1.1)
+    discourse-fonts (0.0.9)
+    discourse-seed-fu (2.3.12)
+      activerecord (>= 3.1)
+      activesupport (>= 3.1)
+    discourse_dev_assets (0.0.4)
+      faker (~> 2.16)
+      literate_randomizer
+    docile (1.4.0)
+    email_reply_trimmer (0.1.13)
+    erubi (1.12.0)
+    excon (0.100.0)
+    execjs (2.8.1)
+    exifr (1.4.0)
+    fabrication (2.30.0)
+    faker (2.23.0)
+      i18n (>= 1.8.11, < 2)
+    fakeweb (1.3.0)
+    faraday (2.7.10)
+      faraday-net_http (>= 2.0, < 3.1)
+      ruby2_keywords (>= 0.0.4)
+    faraday-net_http (3.0.2)
+    faraday-retry (2.2.0)
+      faraday (~> 2.0)
+    fast_blank (1.0.1)
+    fast_xs (0.8.0)
+    fastimage (2.2.7)
+    ffi (1.15.5)
+    fspath (3.1.2)
+    gc_tracer (1.5.1)
+    globalid (1.1.0)
+      activesupport (>= 5.0)
+    google-protobuf (3.23.4)
+    guess_html_encoding (0.0.11)
+    hana (1.3.7)
+    hashdiff (1.0.1)
+    hashie (5.0.0)
+    highline (2.1.0)
+    hkdf (1.0.0)
+    htmlentities (4.3.4)
+    http_accept_language (2.1.1)
+    i18n (1.14.1)
+      concurrent-ruby (~> 1.0)
+    image_optim (0.31.3)
+      exifr (~> 1.2, >= 1.2.2)
+      fspath (~> 3.0)
+      image_size (>= 1.5, < 4)
+      in_threads (~> 1.3)
+      progress (~> 3.0, >= 3.0.1)
+    image_size (3.3.0)
+    in_threads (1.6.0)
+    jmespath (1.6.2)
+    json (2.6.3)
+    json-schema (3.0.0)
+      addressable (>= 2.8)
+    json_schemer (1.0.3)
+      hana (~> 1.3)
+      regexp_parser (~> 2.0)
+      simpleidn (~> 0.2)
+    jwt (2.7.1)
+    kgio (2.11.4)
+    language_server-protocol (3.17.0.3)
+    libv8-node (18.16.0.0)
+    listen (3.8.0)
+      rb-fsevent (~> 0.10, >= 0.10.3)
+      rb-inotify (~> 0.9, >= 0.9.10)
+    literate_randomizer (0.4.0)
+    lograge (0.13.0)
+      actionpack (>= 4)
+      activesupport (>= 4)
+      railties (>= 4)
+      request_store (~> 1.0)
+    logstash-event (1.2.02)
+    logstash-logger (0.26.1)
+      logstash-event (~> 1.2)
+    logster (2.12.2)
+    loofah (2.21.3)
+      crass (~> 1.0.2)
+      nokogiri (>= 1.12.0)
+    lru_redux (1.1.0)
+    lz4-ruby (0.3.3)
+    mail (2.8.1)
+      mini_mime (>= 0.1.1)
+      net-imap
+      net-pop
+      net-smtp
+    matrix (0.4.2)
+    maxminddb (0.1.22)
+    memory_profiler (1.0.1)
+    message_bus (4.3.7)
+      rack (>= 1.1.3)
+    method_source (1.0.0)
+    mini_mime (1.1.2)
+    mini_portile2 (2.8.4)
+    mini_racer (0.8.0)
+      libv8-node (~> 18.16.0.0)
+    mini_scheduler (0.16.0)
+      sidekiq (>= 4.2.3, < 7.0)
+    mini_sql (1.4.0)
+    mini_suffix (0.3.3)
+      ffi (~> 1.9)
+    minitest (5.19.0)
+    mocha (2.1.0)
+      ruby2_keywords (>= 0.0.5)
+    msgpack (1.7.2)
+    multi_json (1.15.0)
+    multi_xml (0.6.0)
+    mustache (1.1.1)
+    net-http (0.3.2)
+      uri
+    net-imap (0.3.7)
+      date
+      net-protocol
+    net-pop (0.1.2)
+      net-protocol
+    net-protocol (0.2.1)
+      timeout
+    net-smtp (0.3.3)
+      net-protocol
+    nio4r (2.5.9)
+    nokogiri (1.15.3)
+      mini_portile2 (~> 2.8.2)
+      racc (~> 1.4)
+    oauth (1.1.0)
+      oauth-tty (~> 1.0, >= 1.0.1)
+      snaky_hash (~> 2.0)
+      version_gem (~> 1.1)
+    oauth-tty (1.0.5)
+      version_gem (~> 1.1, >= 1.1.1)
+    oauth2 (1.4.11)
+      faraday (>= 0.17.3, < 3.0)
+      jwt (>= 1.0, < 3.0)
+      multi_json (~> 1.3)
+      multi_xml (~> 0.5)
+      rack (>= 1.2, < 4)
+    oj (3.15.1)
+    omniauth (1.9.2)
+      hashie (>= 3.4.6)
+      rack (>= 1.6.2, < 3)
+    omniauth-facebook (9.0.0)
+      omniauth-oauth2 (~> 1.2)
+    omniauth-github (1.4.0)
+      omniauth (~> 1.5)
+      omniauth-oauth2 (>= 1.4.0, < 2.0)
+    omniauth-google-oauth2 (0.8.2)
+      jwt (>= 2.0)
+      oauth2 (~> 1.1)
+      omniauth (~> 1.1)
+      omniauth-oauth2 (>= 1.6)
+    omniauth-oauth (1.2.0)
+      oauth
+      omniauth (>= 1.0, < 3)
+    omniauth-oauth2 (1.7.3)
+      oauth2 (>= 1.4, < 3)
+      omniauth (>= 1.9, < 3)
+    omniauth-twitter (1.4.0)
+      omniauth-oauth (~> 1.1)
+      rack
+    openssl (3.1.0)
+    openssl-signature_algorithm (1.3.0)
+      openssl (> 2.0)
+    optimist (3.1.0)
+    parallel (1.23.0)
+    parallel_tests (4.2.1)
+      parallel
+    parser (3.2.2.3)
+      ast (~> 2.4.1)
+      racc
+    pg (1.4.6)
+    prettier_print (1.2.1)
+    progress (3.6.0)
+    pry (0.14.2)
+      coderay (~> 1.1)
+      method_source (~> 1.0)
+    pry-byebug (3.10.1)
+      byebug (~> 11.0)
+      pry (>= 0.13, < 0.15)
+    pry-rails (0.3.9)
+      pry (>= 0.10.4)
+    public_suffix (5.0.3)
+    puma (6.3.0)
+      nio4r (~> 2.0)
+    racc (1.7.1)
+    rack (2.2.8)
+    rack-mini-profiler (3.1.0)
+      rack (>= 1.2.0)
+    rack-protection (3.0.6)
+      rack
+    rack-test (2.1.0)
+      rack (>= 1.3)
+    rails-dom-testing (2.1.1)
+      activesupport (>= 5.0.0)
+      minitest
+      nokogiri (>= 1.6)
+    rails-html-sanitizer (1.6.0)
+      loofah (~> 2.21)
+      nokogiri (~> 1.14)
+    rails_failover (2.0.1)
+      activerecord (>= 6.1, <= 7.1)
+      concurrent-ruby
+      railties (>= 6.1, <= 7.1)
+    rails_multisite (5.0.0)
+      activerecord (>= 6.0)
+      railties (>= 6.0)
+    railties (7.0.5.1)
+      actionpack (= 7.0.5.1)
+      activesupport (= 7.0.5.1)
+      method_source
+      rake (>= 12.2)
+      thor (~> 1.0)
+      zeitwerk (~> 2.5)
+    rainbow (3.1.1)
+    raindrops (0.20.1)
+    rake (13.0.6)
+    rb-fsevent (0.11.2)
+    rb-inotify (0.10.1)
+      ffi (~> 1.0)
+    rbtrace (0.4.14)
+      ffi (>= 1.0.6)
+      msgpack (>= 0.4.3)
+      optimist (>= 3.0.0)
+    rchardet (1.8.0)
+    redis (4.8.1)
+    redis-namespace (1.11.0)
+      redis (>= 4)
+    regexp_parser (2.8.1)
+    request_store (1.5.1)
+      rack (>= 1.4)
+    rexml (3.2.6)
+    rinku (2.0.6)
+    rotp (6.2.2)
+    rouge (4.1.3)
+    rqrcode (2.2.0)
+      chunky_png (~> 1.0)
+      rqrcode_core (~> 1.0)
+    rqrcode_core (1.2.0)
+    rspec (3.12.0)
+      rspec-core (~> 3.12.0)
+      rspec-expectations (~> 3.12.0)
+      rspec-mocks (~> 3.12.0)
+    rspec-core (3.12.2)
+      rspec-support (~> 3.12.0)
+    rspec-expectations (3.12.3)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.12.0)
+    rspec-html-matchers (0.10.0)
+      nokogiri (~> 1)
+      rspec (>= 3.0.0.a)
+    rspec-mocks (3.12.6)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.12.0)
+    rspec-rails (6.0.3)
+      actionpack (>= 6.1)
+      activesupport (>= 6.1)
+      railties (>= 6.1)
+      rspec-core (~> 3.12)
+      rspec-expectations (~> 3.12)
+      rspec-mocks (~> 3.12)
+      rspec-support (~> 3.12)
+    rspec-support (3.12.1)
+    rss (0.2.9)
+      rexml
+    rswag-specs (2.10.1)
+      activesupport (>= 3.1, < 7.1)
+      json-schema (>= 2.2, < 4.0)
+      railties (>= 3.1, < 7.1)
+      rspec-core (>= 2.14)
+    rtlcss (0.2.1)
+      mini_racer (>= 0.6.3)
+    rubocop (1.55.1)
+      json (~> 2.3)
+      language_server-protocol (>= 3.17.0)
+      parallel (~> 1.10)
+      parser (>= 3.2.2.3)
+      rainbow (>= 2.2.2, < 4.0)
+      regexp_parser (>= 1.8, < 3.0)
+      rexml (>= 3.2.5, < 4.0)
+      rubocop-ast (>= 1.28.1, < 2.0)
+      ruby-progressbar (~> 1.7)
+      unicode-display_width (>= 2.4.0, < 3.0)
+    rubocop-ast (1.29.0)
+      parser (>= 3.2.1.0)
+    rubocop-capybara (2.18.0)
+      rubocop (~> 1.41)
+    rubocop-discourse (3.3.0)
+      rubocop (>= 1.1.0)
+      rubocop-rspec (>= 2.0.0)
+    rubocop-factory_bot (2.23.1)
+      rubocop (~> 1.33)
+    rubocop-rspec (2.23.0)
+      rubocop (~> 1.33)
+      rubocop-capybara (~> 2.17)
+      rubocop-factory_bot (~> 2.22)
+    ruby-prof (1.6.3)
+    ruby-progressbar (1.13.0)
+    ruby-readability (0.7.0)
+      guess_html_encoding (>= 0.0.4)
+      nokogiri (>= 1.6.0)
+    ruby2_keywords (0.0.5)
+    rubyzip (2.3.2)
+    sanitize (6.0.2)
+      crass (~> 1.0.2)
+      nokogiri (>= 1.12.0)
+    sass-embedded (1.64.1)
+      google-protobuf (~> 3.23)
+      rake (>= 13.0.0)
+    selenium-webdriver (4.10.0)
+      rexml (~> 3.2, >= 3.2.5)
+      rubyzip (>= 1.2.2, < 3.0)
+      websocket (~> 1.0)
+    sidekiq (6.5.9)
+      connection_pool (>= 2.2.5, < 3)
+      rack (~> 2.0)
+      redis (>= 4.5.0, < 5)
+    simplecov (0.22.0)
+      docile (~> 1.1)
+      simplecov-html (~> 0.11)
+      simplecov_json_formatter (~> 0.1)
+    simplecov-html (0.12.3)
+    simplecov_json_formatter (0.1.4)
+    simpleidn (0.2.1)
+      unf (~> 0.1.4)
+    snaky_hash (2.0.1)
+      hashie
+      version_gem (~> 1.1, >= 1.1.1)
+    sprockets-rails (3.4.2)
+      actionpack (>= 5.2)
+      activesupport (>= 5.2)
+      sprockets (>= 3.0.0)
+    sshkey (2.0.0)
+    stackprof (0.2.25)
+    syntax_tree (6.1.1)
+      prettier_print (>= 1.2.0)
+    syntax_tree-disable_ternary (1.0.0)
+    test-prof (1.2.2)
+    thor (1.2.2)
+    tilt (2.2.0)
+    timeout (0.4.0)
+    tzinfo (2.0.6)
+      concurrent-ruby (~> 1.0)
+    tzinfo-data (1.2023.3)
+      tzinfo (>= 1.0.0)
+    uglifier (4.2.0)
+      execjs (>= 0.3.0, < 3)
+    unf (0.1.4)
+      unf_ext
+    unf_ext (0.0.8.2)
+    unicode-display_width (2.4.2)
+    unicorn (6.1.0)
+      kgio (~> 2.6)
+      raindrops (~> 0.7)
+    uniform_notifier (1.16.0)
+    uri (0.12.2)
+    version_gem (1.1.3)
+    web-push (3.0.0)
+      hkdf (~> 1.0)
+      jwt (~> 2.0)
+      openssl (~> 3.0)
+    webdrivers (5.3.1)
+      nokogiri (~> 1.6)
+      rubyzip (>= 1.3.0)
+      selenium-webdriver (~> 4.0, < 4.11)
+    webmock (3.18.1)
+      addressable (>= 2.8.0)
+      crack (>= 0.3.2)
+      hashdiff (>= 0.4.0, < 2.0.0)
+    websocket (1.2.9)
+    xpath (3.2.0)
+      nokogiri (~> 1.8)
+    yaml-lint (0.1.2)
+    yard (0.9.34)
+    zeitwerk (2.6.10)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  actionmailer (= 7.0.5.1)
+  actionpack (= 7.0.5.1)
+  actionview (= 7.0.5.1)
+  actionview_precompiler
+  active_model_serializers (~> 0.8.3)
+  activemodel (= 7.0.5.1)
+  activerecord (= 7.0.5.1)
+  activesupport (= 7.0.5.1)
+  addressable
+  annotate
+  aws-sdk-s3
+  aws-sdk-sns
+  better_errors
+  binding_of_caller
+  bootsnap
+  bullet
+  byebug
+  capybara
+  cbor
+  certified
+  cgi (>= 0.3.6)
+  colored2
+  cose
+  cppjieba_rb
+  css_parser
+  dartsass-ruby
+  dartsass-sprockets
+  diffy
+  digest
+  discourse-fonts
+  discourse-seed-fu
+  discourse_dev_assets
+  email_reply_trimmer
+  excon
+  execjs
+  fabrication
+  faker (~> 2.16)
+  fakeweb
+  faraday
+  faraday-retry
+  fast_blank
+  fast_xs
+  fastimage
+  gc_tracer
+  highline
+  htmlentities
+  http_accept_language
+  image_optim
+  json
+  json_schemer
+  listen
+  lograge
+  logstash-event
+  logstash-logger
+  logster
+  loofah
+  lru_redux
+  lz4-ruby
+  mail
+  maxminddb
+  memory_profiler
+  message_bus
+  mini_mime
+  mini_racer
+  mini_scheduler
+  mini_sql
+  mini_suffix
+  minitest
+  mocha
+  multi_json
+  mustache
+  net-http
+  net-imap
+  net-pop
+  net-smtp
+  nokogiri
+  oj
+  omniauth
+  omniauth-facebook
+  omniauth-github
+  omniauth-google-oauth2
+  omniauth-oauth2
+  omniauth-twitter
+  parallel_tests
+  pg
+  pry-byebug
+  pry-rails
+  puma
+  rack
+  rack-mini-profiler
+  rack-protection
+  rails-dom-testing
+  rails_failover
+  rails_multisite
+  railties (= 7.0.5.1)
+  rake
+  rb-fsevent
+  rbtrace
+  rchardet
+  redis
+  redis-namespace
+  rinku
+  rotp
+  rqrcode
+  rspec
+  rspec-html-matchers
+  rspec-rails
+  rss
+  rswag-specs
+  rtlcss
+  rubocop-discourse
+  ruby-prof
+  ruby-readability
+  rubyzip
+  sanitize
+  selenium-webdriver
+  shoulda-matchers!
+  sidekiq
+  simplecov
+  sprockets!
+  sprockets-rails
+  sshkey
+  stackprof
+  syntax_tree
+  syntax_tree-disable_ternary
+  test-prof
+  thor
+  tzinfo-data
+  uglifier
+  unf
+  unicorn
+  web-push
+  webdrivers
+  webmock
+  yaml-lint
+  yard
+
+BUNDLED WITH
+   2.4.13
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/gemset.nix b/nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/gemset.nix
new file mode 100644
index 000000000000..fc7b71f0c030
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/rubyEnv/gemset.nix
@@ -0,0 +1,2560 @@
+{
+  actionmailer = {
+    dependencies = ["actionpack" "actionview" "activejob" "activesupport" "mail" "net-imap" "net-pop" "net-smtp" "rails-dom-testing"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1pz26qpdx1xncpy5h8k4afw0npnh6wn580yvwv2cf857zrzvr1pm";
+      type = "gem";
+    };
+    version = "7.0.5.1";
+  };
+  actionpack = {
+    dependencies = ["actionview" "activesupport" "rack" "rack-test" "rails-dom-testing" "rails-html-sanitizer"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "003y7cdxwzdqx8hgw02kf1b5mp8qr8syx07f35sk3ghhqxp39ksy";
+      type = "gem";
+    };
+    version = "7.0.5.1";
+  };
+  actionview = {
+    dependencies = ["activesupport" "builder" "erubi" "rails-dom-testing" "rails-html-sanitizer"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "11ihpqcvz3f38ka85zdjkdcvgdbcan81dbr0y9bi784jn1v5ggwa";
+      type = "gem";
+    };
+    version = "7.0.5.1";
+  };
+  actionview_precompiler = {
+    dependencies = ["actionview"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "07dx8vkwig8han4zccs0chahcf9ibd4abzx9n56qah8zak5cyrhd";
+      type = "gem";
+    };
+    version = "0.2.3";
+  };
+  active_model_serializers = {
+    dependencies = ["activemodel"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0k3mgia2ahh7mbk30hjq9pzqbk0kh281s91kq2z6p555nv9y6l3k";
+      type = "gem";
+    };
+    version = "0.8.4";
+  };
+  activejob = {
+    dependencies = ["activesupport" "globalid"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "11wkxf16zdb9gsnc94x4hyj89wjks06gnk4fbl7gp5vkbl744n83";
+      type = "gem";
+    };
+    version = "7.0.5.1";
+  };
+  activemodel = {
+    dependencies = ["activesupport"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "12f89hxs4s26ggsg4bnz9qxlcsclcgx9gdsl8dni5jc0gk47h14y";
+      type = "gem";
+    };
+    version = "7.0.5.1";
+  };
+  activerecord = {
+    dependencies = ["activemodel" "activesupport"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1sfdq2slmsc0ygncl36dq1lmjww1y3b42izrnn62cyisiag28796";
+      type = "gem";
+    };
+    version = "7.0.5.1";
+  };
+  activesupport = {
+    dependencies = ["concurrent-ruby" "i18n" "minitest" "tzinfo"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0m1sa6djlm9cz6mz3lcbqqahvm6qj75dmq3phpn2ysyxnlz2hr0c";
+      type = "gem";
+    };
+    version = "7.0.5.1";
+  };
+  addressable = {
+    dependencies = ["public_suffix"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "15s8van7r2ad3dq6i03l3z4hqnvxcq75a3h72kxvf9an53sqma20";
+      type = "gem";
+    };
+    version = "2.8.4";
+  };
+  annotate = {
+    dependencies = ["activerecord" "rake"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1lw0fxb5mirsdp3bp20gjyvs7clvi19jbxnrm2ihm20kzfhvlqcs";
+      type = "gem";
+    };
+    version = "3.2.0";
+  };
+  ast = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "04nc8x27hlzlrr5c2gn7mar4vdr0apw5xg22wp6m8dx3wqr04a0y";
+      type = "gem";
+    };
+    version = "2.4.2";
+  };
+  aws-eventstream = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1pyis1nvnbjxk12a43xvgj2gv0mvp4cnkc1gzw0v1018r61399gz";
+      type = "gem";
+    };
+    version = "1.2.0";
+  };
+  aws-partitions = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0bg0v08n9mgvpnvkx8aznrax25lkrfsi5sjfdlccm7dadnada5fg";
+      type = "gem";
+    };
+    version = "1.583.0";
+  };
+  aws-sdk-core = {
+    dependencies = ["aws-eventstream" "aws-partitions" "aws-sigv4" "jmespath"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0hajbavfngn99hcz6n20162jygvwdflldvnlrza7z32hizawaaan";
+      type = "gem";
+    };
+    version = "3.130.2";
+  };
+  aws-sdk-kms = {
+    dependencies = ["aws-sdk-core" "aws-sigv4"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "14dcfqqdx1dy7qwrdyqdvqjs53kswm4njvg34f61jpl9xi3h2yf3";
+      type = "gem";
+    };
+    version = "1.56.0";
+  };
+  aws-sdk-s3 = {
+    dependencies = ["aws-sdk-core" "aws-sdk-kms" "aws-sigv4"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1r6dxz3llgxbbm66jq5mkzk0i6qsxwv0d9s0ipwb23vv3bgp23yf";
+      type = "gem";
+    };
+    version = "1.114.0";
+  };
+  aws-sdk-sns = {
+    dependencies = ["aws-sdk-core" "aws-sigv4"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0d3fhll3hqc23fvj7p0ncjrr0fri7spy21r0hfkqjhijm0q1xqg9";
+      type = "gem";
+    };
+    version = "1.53.0";
+  };
+  aws-sigv4 = {
+    dependencies = ["aws-eventstream"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0xp7diwq7nv4vvxrl9x3lis2l4x6bissrfzbfyy6rv5bmj5w109z";
+      type = "gem";
+    };
+    version = "1.5.0";
+  };
+  better_errors = {
+    dependencies = ["erubi" "rack" "rouge"];
+    groups = ["development"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0wqazisnn6hn1wsza412xribpw5wzx6b5z5p4mcpfgizr6xg367p";
+      type = "gem";
+    };
+    version = "2.10.1";
+  };
+  binding_of_caller = {
+    dependencies = ["debug_inspector"];
+    groups = ["development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "078n2dkpgsivcf0pr50981w95nfc2bsrp3wpf9wnxz1qsp8jbb9s";
+      type = "gem";
+    };
+    version = "1.0.0";
+  };
+  bootsnap = {
+    dependencies = ["msgpack"];
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1vcg52gwl64xhhal6kwk1pc01y1klzdlnv1awyk89kb91z010x7q";
+      type = "gem";
+    };
+    version = "1.16.0";
+  };
+  builder = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "045wzckxpwcqzrjr353cxnyaxgf0qg22jh00dcx7z38cys5g1jlr";
+      type = "gem";
+    };
+    version = "3.2.4";
+  };
+  bullet = {
+    dependencies = ["activesupport" "uniform_notifier"];
+    groups = ["development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0hyz68j0z0j24vcrs43swmlykhzypayv34kzrsbxda5lbi83gynm";
+      type = "gem";
+    };
+    version = "7.0.7";
+  };
+  byebug = {
+    groups = ["development" "test"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0nx3yjf4xzdgb8jkmk2344081gqr22pgjqnmjg2q64mj5d6r9194";
+      type = "gem";
+    };
+    version = "11.1.3";
+  };
+  capybara = {
+    dependencies = ["addressable" "matrix" "mini_mime" "nokogiri" "rack" "rack-test" "regexp_parser" "xpath"];
+    groups = ["test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "114qm5f5vhwaaw9rj1h2lcamh46zl13v1m18jiw68zl961gwmw6n";
+      type = "gem";
+    };
+    version = "3.39.2";
+  };
+  cbor = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0511idr8xps9625nh3kxr68sdy6l3xy2kcz7r57g47fxb1v18jj3";
+      type = "gem";
+    };
+    version = "0.5.9.6";
+  };
+  certified = {
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1706p6p0a8adyvd943af2a3093xakvislgffw3v9dvp7j07dyk5a";
+      type = "gem";
+    };
+    version = "1.0.0";
+  };
+  cgi = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "18zc1z8va9j1gcv131p605wmkvn1p5958mmvvy7v45ki8c0w7qn5";
+      type = "gem";
+    };
+    version = "0.3.6";
+  };
+  chunky_png = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1znw5x86hmm9vfhidwdsijz8m38pqgmv98l9ryilvky0aldv7mc9";
+      type = "gem";
+    };
+    version = "1.4.0";
+  };
+  coderay = {
+    groups = ["default" "development"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0jvxqxzply1lwp7ysn94zjhh57vc14mcshw1ygw14ib8lhc00lyw";
+      type = "gem";
+    };
+    version = "1.1.3";
+  };
+  colored2 = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0jlbqa9q4mvrm73aw9mxh23ygzbjiqwisl32d8szfb5fxvbjng5i";
+      type = "gem";
+    };
+    version = "3.1.2";
+  };
+  concurrent-ruby = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0krcwb6mn0iklajwngwsg850nk8k9b35dhmc2qkbdqvmifdi2y9q";
+      type = "gem";
+    };
+    version = "1.2.2";
+  };
+  connection_pool = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1x32mcpm2cl5492kd6lbjbaf17qsssmpx9kdyr7z1wcif2cwyh0g";
+      type = "gem";
+    };
+    version = "2.4.1";
+  };
+  cose = {
+    dependencies = ["cbor" "openssl-signature_algorithm"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "00c6x4ha7qiaaf88qdbyf240mk146zz78rbm4qwyaxmwlmk7q933";
+      type = "gem";
+    };
+    version = "1.3.0";
+  };
+  cppjieba_rb = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0ijzvnm5jclyhf6ls30kv7dqy05f3hbha69f59jwbzdid7dndla5";
+      type = "gem";
+    };
+    version = "0.4.2";
+  };
+  crack = {
+    dependencies = ["rexml"];
+    groups = ["default" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1cr1kfpw3vkhysvkk3wg7c54m75kd68mbm9rs5azdjdq57xid13r";
+      type = "gem";
+    };
+    version = "0.4.5";
+  };
+  crass = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0pfl5c0pyqaparxaqxi6s4gfl21bdldwiawrc0aknyvflli60lfw";
+      type = "gem";
+    };
+    version = "1.0.6";
+  };
+  css_parser = {
+    dependencies = ["addressable"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "04q1vin8slr3k8mp76qz0wqgap6f9kdsbryvgfq9fljhrm463kpj";
+      type = "gem";
+    };
+    version = "1.14.0";
+  };
+  dartsass-ruby = {
+    dependencies = ["sass-embedded"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0z3gdsnyvdjgn9gwia72irqgxq04i8hv9pv60yqkd4h5nk9rx4p6";
+      type = "gem";
+    };
+    version = "3.0.1";
+  };
+  dartsass-sprockets = {
+    dependencies = ["dartsass-ruby" "railties" "sprockets" "sprockets-rails" "tilt"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1842k5i96iiz264wzzqar2m3whs2caf0d8yhbsr6qdbi4j5pzmcx";
+      type = "gem";
+    };
+    version = "3.0.0";
+  };
+  date = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "03skfikihpx37rc27vr3hwrb057gxnmdzxhmzd4bf4jpkl0r55w1";
+      type = "gem";
+    };
+    version = "3.3.3";
+  };
+  debug_inspector = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "01l678ng12rby6660pmwagmyg8nccvjfgs3487xna7ay378a59ga";
+      type = "gem";
+    };
+    version = "1.1.0";
+  };
+  diff-lcs = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0rwvjahnp7cpmracd8x732rjgnilqv2sx7d1gfrysslc3h039fa9";
+      type = "gem";
+    };
+    version = "1.5.0";
+  };
+  diffy = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1qcsv29ljfhy76gq4xi8zpn6dc6nv15c41r131bdr38kwpxjzd1n";
+      type = "gem";
+    };
+    version = "3.4.2";
+  };
+  digest = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "01qkpbkxq83ip3iysfh2kjrg9sh2n2q91prhyxh3vq10lcfzv9l1";
+      type = "gem";
+    };
+    version = "3.1.1";
+  };
+  discourse-fonts = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1q1q9fmqc7dir2nj94nai58h26zsh6fqmbr6hfax5d6xpy4pm1yf";
+      type = "gem";
+    };
+    version = "0.0.9";
+  };
+  discourse-seed-fu = {
+    dependencies = ["activerecord" "activesupport"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1r3mbi72cx3xx8dnva1zhvxcacdma4xfn16d8s860m7d25fdjqag";
+      type = "gem";
+    };
+    version = "2.3.12";
+  };
+  discourse_dev_assets = {
+    dependencies = ["faker" "literate_randomizer"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0ncd6n34vm7qd5mpza8wrqfkgfc6xbd5rxjcbdnvsv94zxr75rm1";
+      type = "gem";
+    };
+    version = "0.0.4";
+  };
+  docile = {
+    groups = ["default" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1lxqxgq71rqwj1lpl9q1mbhhhhhhdkkj7my341f2889pwayk85sz";
+      type = "gem";
+    };
+    version = "1.4.0";
+  };
+  email_reply_trimmer = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1jgcxifm48xq5dz9k47q43pqm5bfnf14l62l3bqhmv8f6z8dw4ki";
+      type = "gem";
+    };
+    version = "0.1.13";
+  };
+  erubi = {
+    groups = ["default" "development" "test"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "08s75vs9cxlc4r1q2bjg4br8g9wc5lc5x5vl0vv4zq5ivxsdpgi7";
+      type = "gem";
+    };
+    version = "1.12.0";
+  };
+  excon = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "08r6qgbpkxxsihjmlspk3l1sr69q5hx35p1l4wp7rmkbzys89867";
+      type = "gem";
+    };
+    version = "0.100.0";
+  };
+  execjs = {
+    groups = ["assets" "default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "121h6af4i6wr3wxvv84y53jcyw2sk71j5wsncm6wq6yqrwcrk4vd";
+      type = "gem";
+    };
+    version = "2.8.1";
+  };
+  exifr = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "11v201jljn327fwjqcsglrbdnyhivnj7j6nh6wym5zjqgrwxy3kn";
+      type = "gem";
+    };
+    version = "1.4.0";
+  };
+  fabrication = {
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0bxssmjp49whzq2zv7w751gr4nkdaiwcxd1vda0byigwyrnj6f5q";
+      type = "gem";
+    };
+    version = "2.30.0";
+  };
+  faker = {
+    dependencies = ["i18n"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1wslw5gh335zcahxmdd497xaa7h0d8l60c0jfv942mn47fxy8m47";
+      type = "gem";
+    };
+    version = "2.23.0";
+  };
+  fakeweb = {
+    groups = ["test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1a09z9nb369bvwpghncgd5y4f95lh28w0q258srh02h22fz9dj8y";
+      type = "gem";
+    };
+    version = "1.3.0";
+  };
+  faraday = {
+    dependencies = ["faraday-net_http" "ruby2_keywords"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "187clqhp9mv5mnqmjlfdp57svhsg1bggz84ak8v333j9skrnrgh9";
+      type = "gem";
+    };
+    version = "2.7.10";
+  };
+  faraday-net_http = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "13byv3mp1gsjyv8k0ih4612y6vw5kqva6i03wcg4w2fqpsd950k8";
+      type = "gem";
+    };
+    version = "3.0.2";
+  };
+  faraday-retry = {
+    dependencies = ["faraday"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1ia19zgni6cw96rvsr0s004vjs9m2r6la4s00zcff36xaia4m0l0";
+      type = "gem";
+    };
+    version = "2.2.0";
+  };
+  fast_blank = {
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "rbx";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1shpmamyzyhyxmv95r96ja5rylzaw60r19647d0fdm7y2h2c77r6";
+      type = "gem";
+    };
+    version = "1.0.1";
+  };
+  fast_xs = {
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "rbx";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1iydzaqmvqq7ncxkr182aybkk6xap0cb2w9amr73vbdxi2qf3wjz";
+      type = "gem";
+    };
+    version = "0.8.0";
+  };
+  fastimage = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1pd7pamzhdz2w0fbcvsfn2nyslznvphnwj16zw35g2b28zd2xyzx";
+      type = "gem";
+    };
+    version = "2.2.7";
+  };
+  ffi = {
+    groups = ["default" "development" "test"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1862ydmclzy1a0cjbvm8dz7847d9rch495ib0zb64y84d3xd4bkg";
+      type = "gem";
+    };
+    version = "1.15.5";
+  };
+  fspath = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0xcxikkrjv8ws328nn5ax5pyfjs8pn7djg1hks7qyb3yp6prpb5m";
+      type = "gem";
+    };
+    version = "3.1.2";
+  };
+  gc_tracer = {
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1yv3mp8lx74lfzs04fd5h4g89209iwhzpc407y35p7cmzgx6a4kv";
+      type = "gem";
+    };
+    version = "1.5.1";
+  };
+  globalid = {
+    dependencies = ["activesupport"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0kqm5ndzaybpnpxqiqkc41k4ksyxl41ln8qqr6kb130cdxsf2dxk";
+      type = "gem";
+    };
+    version = "1.1.0";
+  };
+  google-protobuf = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1dq5lgkxhagqr8zjrwr10zi8rldbg2vhis2m5q86v5q9415ylfgj";
+      type = "gem";
+    };
+    version = "3.23.4";
+  };
+  guess_html_encoding = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "16700fk6kmif3q3kpc1ldhy3nsc9pkxlgl8sqhznff2zjj5lddna";
+      type = "gem";
+    };
+    version = "0.0.11";
+  };
+  hana = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "03cvrv2wl25j9n4n509hjvqnmwa60k92j741b64a1zjisr1dn9al";
+      type = "gem";
+    };
+    version = "1.3.7";
+  };
+  hashdiff = {
+    groups = ["default" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1nynpl0xbj0nphqx1qlmyggq58ms1phf5i03hk64wcc0a17x1m1c";
+      type = "gem";
+    };
+    version = "1.0.1";
+  };
+  hashie = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1nh3arcrbz1rc1cr59qm53sdhqm137b258y8rcb4cvd3y98lwv4x";
+      type = "gem";
+    };
+    version = "5.0.0";
+  };
+  highline = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1f8cr014j7mdqpdb9q17fp5vb5b8n1pswqaif91s3ylg5x3pygfn";
+      type = "gem";
+    };
+    version = "2.1.0";
+  };
+  hkdf = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "03g3yvfnlcjv2qw3b3yahg0x7zhwcd1bwxyj6gbn5jrc7k4kfrqg";
+      type = "gem";
+    };
+    version = "1.0.0";
+  };
+  htmlentities = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1nkklqsn8ir8wizzlakncfv42i32wc0w9hxp00hvdlgjr7376nhj";
+      type = "gem";
+    };
+    version = "4.3.4";
+  };
+  http_accept_language = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0d0nlfz9vm4jr1l6q0chx4rp2hrnrfbx3gadc1dz930lbbaz0hq0";
+      type = "gem";
+    };
+    version = "2.1.1";
+  };
+  i18n = {
+    dependencies = ["concurrent-ruby"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0qaamqsh5f3szhcakkak8ikxlzxqnv49n2p7504hcz2l0f4nj0wx";
+      type = "gem";
+    };
+    version = "1.14.1";
+  };
+  image_optim = {
+    dependencies = ["exifr" "fspath" "image_size" "in_threads" "progress"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "02iw1plldayr1l8bdw2gshq0h083h0fxwji1m1nfhzikz917c07p";
+      type = "gem";
+    };
+    version = "0.31.3";
+  };
+  image_size = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "19fspid6610sm4x0mql7iny7k0d7f21xgxqmsca0irvlvazwm4vn";
+      type = "gem";
+    };
+    version = "3.3.0";
+  };
+  in_threads = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0j9132d4g8prjafgdh4pw948j527kr09m2lvylrcd797il9yd9wi";
+      type = "gem";
+    };
+    version = "1.6.0";
+  };
+  jmespath = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1cdw9vw2qly7q7r41s7phnac264rbsdqgj4l0h4nqgbjb157g393";
+      type = "gem";
+    };
+    version = "1.6.2";
+  };
+  json = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0nalhin1gda4v8ybk6lq8f407cgfrj6qzn234yra4ipkmlbfmal6";
+      type = "gem";
+    };
+    version = "2.6.3";
+  };
+  json-schema = {
+    dependencies = ["addressable"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0gdvm83yaa5n8hwapwzxwfcmbypiq2i0zfx4mzz67wg55p2cnli4";
+      type = "gem";
+    };
+    version = "3.0.0";
+  };
+  json_schemer = {
+    dependencies = ["hana" "regexp_parser" "simpleidn"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1mbf7v8bzmxyk413y16drnww68bgyzknlqmaqvj785iakja7in7x";
+      type = "gem";
+    };
+    version = "1.0.3";
+  };
+  jwt = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "16z11alz13vfc4zs5l3fk6n51n2jw9lskvc4h4prnww0y797qd87";
+      type = "gem";
+    };
+    version = "2.7.1";
+  };
+  kgio = {
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "rbx";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1ipzvw7n0kz1w8rkqybyxvf3hb601a770khm0xdqm68mc4aa59xx";
+      type = "gem";
+    };
+    version = "2.11.4";
+  };
+  language_server-protocol = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0gvb1j8xsqxms9mww01rmdl78zkd72zgxaap56bhv8j45z05hp1x";
+      type = "gem";
+    };
+    version = "3.17.0.3";
+  };
+  libv8-node = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0n2kakfa4nmkkmjimkg2z4fsni9v0qbwkwn9hcm2xp69xqfcmxiq";
+      type = "gem";
+    };
+    version = "18.16.0.0";
+  };
+  listen = {
+    dependencies = ["rb-fsevent" "rb-inotify"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "13rgkfar8pp31z1aamxf5y7cfq88wv6rxxcwy7cmm177qq508ycn";
+      type = "gem";
+    };
+    version = "3.8.0";
+  };
+  literate_randomizer = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1c8p8aw93bx4ygpkwfv6dv41psb86jb0pi16gvnv30rr72dkq1q5";
+      type = "gem";
+    };
+    version = "0.4.0";
+  };
+  lograge = {
+    dependencies = ["actionpack" "activesupport" "railties" "request_store"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "01kdw5dbzimb89rq4zf44zf8990czb5qxvib0hzja1l4hrha8cki";
+      type = "gem";
+    };
+    version = "0.13.0";
+  };
+  logstash-event = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1bk7fhhryjxp1klr3hq6i6srrc21wl4p980bysjp0w66z9hdr9w9";
+      type = "gem";
+    };
+    version = "1.2.02";
+  };
+  logstash-logger = {
+    dependencies = ["logstash-event"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1nh0jgz4rl46axqb9l0fa866kh34wb7yf11qc3j30xhprdqb8yjp";
+      type = "gem";
+    };
+    version = "0.26.1";
+  };
+  logster = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "18yqcf756rzxdq5pw2qrximfryv15ib7rv2g622wjig7zhvk8wx4";
+      type = "gem";
+    };
+    version = "2.12.2";
+  };
+  loofah = {
+    dependencies = ["crass" "nokogiri"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1p744kjpb5zk2ihklbykzii77alycjc04vpnm2ch2f3cp65imlj3";
+      type = "gem";
+    };
+    version = "2.21.3";
+  };
+  lru_redux = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1yxghzg7476sivz8yyr9nkak2dlbls0b89vc2kg52k0nmg6d0wgf";
+      type = "gem";
+    };
+    version = "1.1.0";
+  };
+  lz4-ruby = {
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "rbx";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "12fymsvcb9kw6ycyfzc8b9svriq0afqf1qnl121xrz8c4gpfa6q1";
+      type = "gem";
+    };
+    version = "0.3.3";
+  };
+  mail = {
+    dependencies = ["mini_mime" "net-imap" "net-pop" "net-smtp"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1bf9pysw1jfgynv692hhaycfxa8ckay1gjw5hz3madrbrynryfzc";
+      type = "gem";
+    };
+    version = "2.8.1";
+  };
+  matrix = {
+    groups = ["default" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1h2cgkpzkh3dd0flnnwfq6f3nl2b1zff9lvqz8xs853ssv5kq23i";
+      type = "gem";
+    };
+    version = "0.4.2";
+  };
+  maxminddb = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0zlhqilyggiryywgswfi624bv10qnkm66hggmg79vvgv73j3p4sh";
+      type = "gem";
+    };
+    version = "0.1.22";
+  };
+  memory_profiler = {
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1c81d68r4wx0ckbmqxlfqc2qpd94jwcmqdm0xgr0s46r48pv9k9q";
+      type = "gem";
+    };
+    version = "1.0.1";
+  };
+  message_bus = {
+    dependencies = ["rack"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1ppqgch8xxccpmccdx37lb00112ayqjb80zz5m3w3298vdzb1kn4";
+      type = "gem";
+    };
+    version = "4.3.7";
+  };
+  method_source = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1pnyh44qycnf9mzi1j6fywd5fkskv3x7nmsqrrws0rjn5dd4ayfp";
+      type = "gem";
+    };
+    version = "1.0.0";
+  };
+  mini_mime = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0lbim375gw2dk6383qirz13hgdmxlan0vc5da2l072j3qw6fqjm5";
+      type = "gem";
+    };
+    version = "1.1.2";
+  };
+  mini_portile2 = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "02mj8mpd6ck5gpcnsimx5brzggw5h5mmmpq2djdypfq16wcw82qq";
+      type = "gem";
+    };
+    version = "2.8.4";
+  };
+  mini_racer = {
+    dependencies = ["libv8-node"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0zjf3jsbara8fpfky28z1f64ymk5qsq40i527fxdnw061hlm4izy";
+      type = "gem";
+    };
+    version = "0.8.0";
+  };
+  mini_scheduler = {
+    dependencies = ["sidekiq"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "19c72wlr0zsrg1fiak61h0z1b3glv2l23041xvlwv2i71fw5xavy";
+      type = "gem";
+    };
+    version = "0.16.0";
+  };
+  mini_sql = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1dgwyyya821sfj4f92sljsxmmnak2yrzsbckvy82001zgq1n3b41";
+      type = "gem";
+    };
+    version = "1.4.0";
+  };
+  mini_suffix = {
+    dependencies = ["ffi"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1rr2nx1kixd7ccxqdnswjnflg46s6lr1f9vxkdy298k95zwk67cd";
+      type = "gem";
+    };
+    version = "0.3.3";
+  };
+  minitest = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0jnpsbb2dbcs95p4is4431l2pw1l5pn7dfg3vkgb4ga464j0c5l6";
+      type = "gem";
+    };
+    version = "5.19.0";
+  };
+  mocha = {
+    dependencies = ["ruby2_keywords"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0lsll8iba8612dypk718l9kx73m9syiscb2rhciljys1krc5g1zr";
+      type = "gem";
+    };
+    version = "2.1.0";
+  };
+  msgpack = {
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1a5adcb7bwan09mqhj3wi9ib52hmdzmqg7q08pggn3adibyn5asr";
+      type = "gem";
+    };
+    version = "1.7.2";
+  };
+  multi_json = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0pb1g1y3dsiahavspyzkdy39j4q377009f6ix0bh1ag4nqw43l0z";
+      type = "gem";
+    };
+    version = "1.15.0";
+  };
+  multi_xml = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0lmd4f401mvravi1i1yq7b2qjjli0yq7dfc4p1nj5nwajp7r6hyj";
+      type = "gem";
+    };
+    version = "0.6.0";
+  };
+  mustache = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1l0p4wx15mi3wnamfv92ipkia4nsx8qi132c6g51jfdma3fiz2ch";
+      type = "gem";
+    };
+    version = "1.1.1";
+  };
+  net-http = {
+    dependencies = ["uri"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0y55ib1v2b8prqfi9ij7hca60b1j94s2bzr6vskwi3i5735472wq";
+      type = "gem";
+    };
+    version = "0.3.2";
+  };
+  net-imap = {
+    dependencies = ["date" "net-protocol"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0lf7wqg7czhaj51qsnmn28j7jmcxhkh3m28rl1cjrqsgjxhwj7r3";
+      type = "gem";
+    };
+    version = "0.3.7";
+  };
+  net-pop = {
+    dependencies = ["net-protocol"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1wyz41jd4zpjn0v1xsf9j778qx1vfrl24yc20cpmph8k42c4x2w4";
+      type = "gem";
+    };
+    version = "0.1.2";
+  };
+  net-protocol = {
+    dependencies = ["timeout"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0dxckrlw4q1lcn3qg4mimmjazmg9bma5gllv72f8js3p36fb3b91";
+      type = "gem";
+    };
+    version = "0.2.1";
+  };
+  net-smtp = {
+    dependencies = ["net-protocol"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1c6md06hm5bf6rv53sk54dl2vg038pg8kglwv3rayx0vk2mdql9x";
+      type = "gem";
+    };
+    version = "0.3.3";
+  };
+  nio4r = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0w9978zwjf1qhy3amkivab0f9syz6a7k0xgydjidaf7xc831d78f";
+      type = "gem";
+    };
+    version = "2.5.9";
+  };
+  nokogiri = {
+    dependencies = ["mini_portile2" "racc"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1jw8a20a9k05fpz3q24im19b97idss3179z76yn5scc5b8lk2rl7";
+      type = "gem";
+    };
+    version = "1.15.3";
+  };
+  oauth = {
+    dependencies = ["oauth-tty" "snaky_hash" "version_gem"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1syx3hfimaqycy21kn8gmal1cb3bw3hzalv3in2ixnay1xzjp41q";
+      type = "gem";
+    };
+    version = "1.1.0";
+  };
+  oauth-tty = {
+    dependencies = ["version_gem"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "05wb5n36i4h23hh9dx2m2cwjxx5vj0vgyrn2xr6rsl54glq5rqil";
+      type = "gem";
+    };
+    version = "1.0.5";
+  };
+  oauth2 = {
+    dependencies = ["faraday" "jwt" "multi_json" "multi_xml" "rack"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "042w5lamxhllfxsv0y8v9cvdhmlasy5kxbhcdd3lzj9bhz4gqfb7";
+      type = "gem";
+    };
+    version = "1.4.11";
+  };
+  oj = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1vzcrsv6w5k90l75gy83dlfkv2z9pvnr82mz1nhnijmcg3rgqaz8";
+      type = "gem";
+    };
+    version = "3.15.1";
+  };
+  omniauth = {
+    dependencies = ["hashie" "rack"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1jn9j54l5h7xcba2vjq74l1dk0xrwvsjxam4qhylpi52nw0h5502";
+      type = "gem";
+    };
+    version = "1.9.2";
+  };
+  omniauth-facebook = {
+    dependencies = ["omniauth-oauth2"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0m7q38kjm94wgq6h7hk9546yg33wcs3vf1v6zp0vx7nwkvfxh2j4";
+      type = "gem";
+    };
+    version = "9.0.0";
+  };
+  omniauth-github = {
+    dependencies = ["omniauth" "omniauth-oauth2"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0xbk0dbxqfpyfb33ghz6vrlz3m6442rp18ryf13gwzlnifcawhlb";
+      type = "gem";
+    };
+    version = "1.4.0";
+  };
+  omniauth-google-oauth2 = {
+    dependencies = ["jwt" "oauth2" "omniauth" "omniauth-oauth2"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "10pnxvb6wpnf58dja3yz4ja527443x3q13hzhcbays4amnnp8i4a";
+      type = "gem";
+    };
+    version = "0.8.2";
+  };
+  omniauth-oauth = {
+    dependencies = ["oauth" "omniauth"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0yw2vzx633p9wpdkd4jxsih6mw604mj7f6myyfikmj4d95c8d9z7";
+      type = "gem";
+    };
+    version = "1.2.0";
+  };
+  omniauth-oauth2 = {
+    dependencies = ["oauth2" "omniauth"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0ia73zcbmhf02krlkq2rxmksx93jp777ax5x58fzkq3jzacqyniz";
+      type = "gem";
+    };
+    version = "1.7.3";
+  };
+  omniauth-twitter = {
+    dependencies = ["omniauth-oauth" "rack"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0r5j65hkpgzhvvbs90id3nfsjgsad6ymzggbm7zlaxvnrmvnrk65";
+      type = "gem";
+    };
+    version = "1.4.0";
+  };
+  openssl = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0c649921vg2l939z5cc3jwd8p1v49099pdhxfk7sb9qqx5wi5873";
+      type = "gem";
+    };
+    version = "3.1.0";
+  };
+  openssl-signature_algorithm = {
+    dependencies = ["openssl"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "103yjl68wqhl5kxaciir5jdnyi7iv9yckishdr52s5knh9g0pd53";
+      type = "gem";
+    };
+    version = "1.3.0";
+  };
+  optimist = {
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0q4jqq3v1bxlfr9jgqmahnygkvl81lr6s1rhm8qg66c9xr9nz241";
+      type = "gem";
+    };
+    version = "3.1.0";
+  };
+  parallel = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0jcc512l38c0c163ni3jgskvq1vc3mr8ly5pvjijzwvfml9lf597";
+      type = "gem";
+    };
+    version = "1.23.0";
+  };
+  parallel_tests = {
+    dependencies = ["parallel"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "04y02j0kyhfww41dnnjawn2gpp24smq0x21dvaa5z6pnq0fvmahv";
+      type = "gem";
+    };
+    version = "4.2.1";
+  };
+  parser = {
+    dependencies = ["ast" "racc"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1swigds85jddb5gshll1g8lkmbcgbcp9bi1d4nigwvxki8smys0h";
+      type = "gem";
+    };
+    version = "3.2.2.3";
+  };
+  pg = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "07m6lxljabw9kyww5k5lgsxsznsm1v5l14r1la09gqka9b5kv3yr";
+      type = "gem";
+    };
+    version = "1.4.6";
+  };
+  prettier_print = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1ybgks9862zmlx71zd4j20ky86fsrp6j6m0az4hzzb1zyaskha57";
+      type = "gem";
+    };
+    version = "1.2.1";
+  };
+  progress = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0wymdk40cwrqn32gwg1kw94s5p1n0z3n7ma7x1s62gd4vw3d63in";
+      type = "gem";
+    };
+    version = "3.6.0";
+  };
+  pry = {
+    dependencies = ["coderay" "method_source"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0k9kqkd9nps1w1r1rb7wjr31hqzkka2bhi8b518x78dcxppm9zn4";
+      type = "gem";
+    };
+    version = "0.14.2";
+  };
+  pry-byebug = {
+    dependencies = ["byebug" "pry"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1y41al94ks07166qbp2200yzyr5y60hm7xaiw4lxpgsm4b1pbyf8";
+      type = "gem";
+    };
+    version = "3.10.1";
+  };
+  pry-rails = {
+    dependencies = ["pry"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1cf4ii53w2hdh7fn8vhqpzkymmchjbwij4l3m7s6fsxvb9bn51j6";
+      type = "gem";
+    };
+    version = "0.3.9";
+  };
+  public_suffix = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0n9j7mczl15r3kwqrah09cxj8hxdfawiqxa60kga2bmxl9flfz9k";
+      type = "gem";
+    };
+    version = "5.0.3";
+  };
+  puma = {
+    dependencies = ["nio4r"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1v7fmv0n4bhdcwh60dgza44iqai5pg34f5pzm4vh4i5fwx7mpqxh";
+      type = "gem";
+    };
+    version = "6.3.0";
+  };
+  racc = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "11v3l46mwnlzlc371wr3x6yylpgafgwdf0q7hc7c1lzx6r414r5g";
+      type = "gem";
+    };
+    version = "1.7.1";
+  };
+  rack = {
+    groups = ["default" "development" "test"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "15rdwbyk71c9nxvd527bvb8jxkcys8r3dj3vqra5b3sa63qs30vv";
+      type = "gem";
+    };
+    version = "2.2.8";
+  };
+  rack-mini-profiler = {
+    dependencies = ["rack"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "13dhpp1iljhqp9c8akmp6gjhx47qf83w12ns4bif26ldkignpam1";
+      type = "gem";
+    };
+    version = "3.1.0";
+  };
+  rack-protection = {
+    dependencies = ["rack"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1kpm67az1wxlg76h620in2r7agfyhv177ps268j5ggsanzddzih8";
+      type = "gem";
+    };
+    version = "3.0.6";
+  };
+  rack-test = {
+    dependencies = ["rack"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1ysx29gk9k14a14zsp5a8czys140wacvp91fja8xcja0j1hzqq8c";
+      type = "gem";
+    };
+    version = "2.1.0";
+  };
+  rails-dom-testing = {
+    dependencies = ["activesupport" "minitest" "nokogiri"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "17g05y7q7934z0ib4aph8h71c2qwjmlakkm7nb2ab45q0aqkfgjd";
+      type = "gem";
+    };
+    version = "2.1.1";
+  };
+  rails-html-sanitizer = {
+    dependencies = ["loofah" "nokogiri"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1pm4z853nyz1bhhqr7fzl44alnx4bjachcr6rh6qjj375sfz3sc6";
+      type = "gem";
+    };
+    version = "1.6.0";
+  };
+  rails_failover = {
+    dependencies = ["activerecord" "concurrent-ruby" "railties"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "102v7928nyl1w1cmi70zbx42nw25v842r84gwchwijwnd2f30gvy";
+      type = "gem";
+    };
+    version = "2.0.1";
+  };
+  rails_multisite = {
+    dependencies = ["activerecord" "railties"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0hilr3yhnzvzn3p2cl77im9ypvbfjk1vw7f72i1j7fi2bmq1h2hi";
+      type = "gem";
+    };
+    version = "5.0.0";
+  };
+  railties = {
+    dependencies = ["actionpack" "activesupport" "method_source" "rake" "thor" "zeitwerk"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1z4lqqbd4i5izsg97mx5yf3gj7y5d07wgvad0jzjghjg12pf142i";
+      type = "gem";
+    };
+    version = "7.0.5.1";
+  };
+  rainbow = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0smwg4mii0fm38pyb5fddbmrdpifwv22zv3d3px2xx497am93503";
+      type = "gem";
+    };
+    version = "3.1.1";
+  };
+  raindrops = {
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "rbx";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0c27mcglrj928zkm4d2spj9yh2xkkka8ns5s6bidkwild3zvj3ma";
+      type = "gem";
+    };
+    version = "0.20.1";
+  };
+  rake = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "15whn7p9nrkxangbs9hh75q585yfn66lv0v2mhj6q6dl6x8bzr2w";
+      type = "gem";
+    };
+    version = "13.0.6";
+  };
+  rb-fsevent = {
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1zmf31rnpm8553lqwibvv3kkx0v7majm1f341xbxc0bk5sbhp423";
+      type = "gem";
+    };
+    version = "0.11.2";
+  };
+  rb-inotify = {
+    dependencies = ["ffi"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1jm76h8f8hji38z3ggf4bzi8vps6p7sagxn3ab57qc0xyga64005";
+      type = "gem";
+    };
+    version = "0.10.1";
+  };
+  rbtrace = {
+    dependencies = ["ffi" "msgpack" "optimist"];
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0s8prj0klfgpmpfcpdzbf149qrrsdxgnb6w6kkqc9gyars4vyaqn";
+      type = "gem";
+    };
+    version = "0.4.14";
+  };
+  rchardet = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1isj1b3ywgg2m1vdlnr41lpvpm3dbyarf1lla4dfibfmad9csfk9";
+      type = "gem";
+    };
+    version = "1.8.0";
+  };
+  redis = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0fikjg6j12ka6hh36dxzhfkpqqmilzjfzcdf59iwkzsgd63f0ziq";
+      type = "gem";
+    };
+    version = "4.8.1";
+  };
+  redis-namespace = {
+    dependencies = ["redis"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0f92i9cwlp6xj6fyn7qn4qsaqvxfw4wqvayll7gbd26qnai1l6p9";
+      type = "gem";
+    };
+    version = "1.11.0";
+  };
+  regexp_parser = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "136br91alxdwh1s85z912dwz23qlhm212vy6i3wkinz3z8mkxxl3";
+      type = "gem";
+    };
+    version = "2.8.1";
+  };
+  request_store = {
+    dependencies = ["rack"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "13ppgmsbrqah08j06bybd3cddv6dml79yzyjn7r8j1src78h98h7";
+      type = "gem";
+    };
+    version = "1.5.1";
+  };
+  rexml = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "05i8518ay14kjbma550mv0jm8a6di8yp5phzrd8rj44z9qnrlrp0";
+      type = "gem";
+    };
+    version = "3.2.6";
+  };
+  rinku = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0zcdha17s1wzxyc5814j6319wqg33jbn58pg6wmxpws36476fq4b";
+      type = "gem";
+    };
+    version = "2.0.6";
+  };
+  rotp = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "10mmzc85y7andsich586ndykw678qn1ns2wpjxrg0sc0gr4w3pig";
+      type = "gem";
+    };
+    version = "6.2.2";
+  };
+  rouge = {
+    groups = ["default" "development"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "19drl3x8fw65v3mpy7fk3cf3dfrywz5alv98n2rm4pp04vdn71lw";
+      type = "gem";
+    };
+    version = "4.1.3";
+  };
+  rqrcode = {
+    dependencies = ["chunky_png" "rqrcode_core"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1hggzz8i1l62pkkiybhiqv6ypxw7q844sddrrbbfczjcnj5sivi3";
+      type = "gem";
+    };
+    version = "2.2.0";
+  };
+  rqrcode_core = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "06ld6386hbdhy5h0k09axmgn424kavpc8f27k1vjhknjhbf8jjfg";
+      type = "gem";
+    };
+    version = "1.2.0";
+  };
+  rspec = {
+    dependencies = ["rspec-core" "rspec-expectations" "rspec-mocks"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "171rc90vcgjl8p1bdrqa92ymrj8a87qf6w20x05xq29mljcigi6c";
+      type = "gem";
+    };
+    version = "3.12.0";
+  };
+  rspec-core = {
+    dependencies = ["rspec-support"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0l95bnjxdabrn79hwdhn2q1n7mn26pj7y1w5660v5qi81x458nqm";
+      type = "gem";
+    };
+    version = "3.12.2";
+  };
+  rspec-expectations = {
+    dependencies = ["diff-lcs" "rspec-support"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "05j44jfqlv7j2rpxb5vqzf9hfv7w8ba46wwgxwcwd8p0wzi1hg89";
+      type = "gem";
+    };
+    version = "3.12.3";
+  };
+  rspec-html-matchers = {
+    dependencies = ["nokogiri" "rspec"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1bp9q28qw4xmxknrrp3ppcr08bbcnnand6r9prw4920407mvy96l";
+      type = "gem";
+    };
+    version = "0.10.0";
+  };
+  rspec-mocks = {
+    dependencies = ["diff-lcs" "rspec-support"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1gq7gviwpck7fhp4y5ibljljvxgjklza18j62qf6zkm2icaa8lfy";
+      type = "gem";
+    };
+    version = "3.12.6";
+  };
+  rspec-rails = {
+    dependencies = ["actionpack" "activesupport" "railties" "rspec-core" "rspec-expectations" "rspec-mocks" "rspec-support"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "086qdyz7c4s5dslm6j06mq7j4jmj958whc3yinhabnqqmz7i463d";
+      type = "gem";
+    };
+    version = "6.0.3";
+  };
+  rspec-support = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1ky86j3ksi26ng9ybd7j0qsdf1lpr8mzrmn98yy9gzv801fvhsgr";
+      type = "gem";
+    };
+    version = "3.12.1";
+  };
+  rss = {
+    dependencies = ["rexml"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1b1zx07kr64kkpm4lssd4r1a1qyr829ppmfl85i4adcvx9mqfid0";
+      type = "gem";
+    };
+    version = "0.2.9";
+  };
+  rswag-specs = {
+    dependencies = ["activesupport" "json-schema" "railties" "rspec-core"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0p0blh8p6zj8vsiw585wiy6zpyn8p3ksn0z92ijfzaw7afvcvl8j";
+      type = "gem";
+    };
+    version = "2.10.1";
+  };
+  rtlcss = {
+    dependencies = ["mini_racer"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0q5zlx1k4gqyq0rvnfkljvrwa73ysycxc5m5ly9py9k1pw05lg91";
+      type = "gem";
+    };
+    version = "0.2.1";
+  };
+  rubocop = {
+    dependencies = ["json" "language_server-protocol" "parallel" "parser" "rainbow" "regexp_parser" "rexml" "rubocop-ast" "ruby-progressbar" "unicode-display_width"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0s9p5qaqq68h5s3ys8xlk9swccma7arjif1w58987n6gicrsprrm";
+      type = "gem";
+    };
+    version = "1.55.1";
+  };
+  rubocop-ast = {
+    dependencies = ["parser"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "188bs225kkhrb17dsf3likdahs2p1i1sqn0pr3pvlx50g6r2mnni";
+      type = "gem";
+    };
+    version = "1.29.0";
+  };
+  rubocop-capybara = {
+    dependencies = ["rubocop"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "01fn05a87g009ch1sh00abdmgjab87i995msap26vxq1a5smdck6";
+      type = "gem";
+    };
+    version = "2.18.0";
+  };
+  rubocop-discourse = {
+    dependencies = ["rubocop" "rubocop-rspec"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1sycsgagz7iq4j4aflzkzjlclvsck9yacjlj1pzzmfpjbbka34x8";
+      type = "gem";
+    };
+    version = "3.3.0";
+  };
+  rubocop-factory_bot = {
+    dependencies = ["rubocop"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0kqchl8f67k2g56sq2h1sm2wb6br5gi47s877hlz94g5086f77n1";
+      type = "gem";
+    };
+    version = "2.23.1";
+  };
+  rubocop-rspec = {
+    dependencies = ["rubocop" "rubocop-capybara" "rubocop-factory_bot"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0l364y00bw1zcs3grdxcxpn48vfrjds2khsiaxjqq3r9grvbprfy";
+      type = "gem";
+    };
+    version = "2.23.0";
+  };
+  ruby-prof = {
+    groups = ["development"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "13fsfw43zx9pcix1fzxb95g09yadqjvc8971k74krrjz81vbyh51";
+      type = "gem";
+    };
+    version = "1.6.3";
+  };
+  ruby-progressbar = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0cwvyb7j47m7wihpfaq7rc47zwwx9k4v7iqd9s1xch5nm53rrz40";
+      type = "gem";
+    };
+    version = "1.13.0";
+  };
+  ruby-readability = {
+    dependencies = ["guess_html_encoding" "nokogiri"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "15ivhbry7hf82lww1bzcrwfyjymijfb3rb0wdd32g2z0942wdspa";
+      type = "gem";
+    };
+    version = "0.7.0";
+  };
+  ruby2_keywords = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1vz322p8n39hz3b4a9gkmz9y7a5jaz41zrm2ywf31dvkqm03glgz";
+      type = "gem";
+    };
+    version = "0.0.5";
+  };
+  rubyzip = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0grps9197qyxakbpw02pda59v45lfgbgiyw48i0mq9f2bn9y6mrz";
+      type = "gem";
+    };
+    version = "2.3.2";
+  };
+  sanitize = {
+    dependencies = ["crass" "nokogiri"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1kymrjdpbmn4yaml3aaqyj1dzj8gqmm9h030dc2rj5mvja7fpi28";
+      type = "gem";
+    };
+    version = "6.0.2";
+  };
+  sass-embedded = {
+    dependencies = ["google-protobuf" "rake"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "15k44qn8vk8ap8khkmpsiw40pywm9pkx4a5yhm8vfi2rgqci9k90";
+      type = "gem";
+    };
+    version = "1.64.1";
+  };
+  selenium-webdriver = {
+    dependencies = ["rexml" "rubyzip" "websocket"];
+    groups = ["test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0hwxxvx6j95ln82pjmrgyzg6qmf511dkcp5q79n6m5m8z4way8m3";
+      type = "gem";
+    };
+    version = "4.10.0";
+  };
+  shoulda-matchers = {
+    dependencies = ["activesupport"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      fetchSubmodules = false;
+      rev = "783a90554053002017510285bc736099b2749c22";
+      sha256 = "10rw7ksi462fxamap6kimdy7hpdgx8477r6zs1kgrbakx24dm3wx";
+      type = "git";
+      url = "https://github.com/thoughtbot/shoulda-matchers.git";
+    };
+    version = "5.3.0";
+  };
+  sidekiq = {
+    dependencies = ["connection_pool" "rack" "redis"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0iv7vgqyrpymiwvc3ca24sl4lda8m627p657p0v4xzdpzincrnbr";
+      type = "gem";
+    };
+    version = "6.5.9";
+  };
+  simplecov = {
+    dependencies = ["docile" "simplecov-html" "simplecov_json_formatter"];
+    groups = ["test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "198kcbrjxhhzca19yrdcd6jjj9sb51aaic3b0sc3pwjghg3j49py";
+      type = "gem";
+    };
+    version = "0.22.0";
+  };
+  simplecov-html = {
+    groups = ["default" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0yx01bxa8pbf9ip4hagqkp5m0mqfnwnw2xk8kjraiywz4lrss6jb";
+      type = "gem";
+    };
+    version = "0.12.3";
+  };
+  simplecov_json_formatter = {
+    groups = ["default" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0a5l0733hj7sk51j81ykfmlk2vd5vaijlq9d5fn165yyx3xii52j";
+      type = "gem";
+    };
+    version = "0.1.4";
+  };
+  simpleidn = {
+    dependencies = ["unf"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "06f7w6ph3bzzqk212yylfp4jfx275shgp9zg3xszbpv1ny2skp9m";
+      type = "gem";
+    };
+    version = "0.2.1";
+  };
+  snaky_hash = {
+    dependencies = ["hashie" "version_gem"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0cfwvdcr46pk0c7m5aw2w3izbrp1iba0q7l21r37mzpwaz0pxj0s";
+      type = "gem";
+    };
+    version = "2.0.1";
+  };
+  sprockets = {
+    dependencies = ["concurrent-ruby" "rack"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      fetchSubmodules = false;
+      rev = "f4d3dae71ef29c44b75a49cfbf8032cce07b423a";
+      sha256 = "0ps1zb411nrwih0rdp6vrnx0n4n18jcwks2x06iw52gvswlv49ry";
+      type = "git";
+      url = "https://github.com/rails/sprockets";
+    };
+    version = "3.7.2";
+  };
+  sprockets-rails = {
+    dependencies = ["actionpack" "activesupport" "sprockets"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1b9i14qb27zs56hlcc2hf139l0ghbqnjpmfi0054dxycaxvk5min";
+      type = "gem";
+    };
+    version = "3.4.2";
+  };
+  sshkey = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "03bkn55qsng484iqwz2lmm6rkimj01vsvhwk661s3lnmpkl65lbp";
+      type = "gem";
+    };
+    version = "2.0.0";
+  };
+  stackprof = {
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0bhdgfb0pmw9mav1kw9fn0ka012sa0i3h5ppvqssw5xq48nhxnr8";
+      type = "gem";
+    };
+    version = "0.2.25";
+  };
+  syntax_tree = {
+    dependencies = ["prettier_print"];
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "162m5xhbiq315bncp49ziddws537dv09pqsgrzsrmhhsymhgy0zb";
+      type = "gem";
+    };
+    version = "6.1.1";
+  };
+  syntax_tree-disable_ternary = {
+    groups = ["development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0gdi6zx4hqpxd81zas3dlw1jrdp98fvsqj4p7f42x5lhpfzz04zc";
+      type = "gem";
+    };
+    version = "1.0.0";
+  };
+  test-prof = {
+    groups = ["test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "08j5456rdpgxvv8bs44x81jrxzpxb79wxfxdq4fqwxyircxzi2jj";
+      type = "gem";
+    };
+    version = "1.2.2";
+  };
+  thor = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0k7j2wn14h1pl4smibasw0bp66kg626drxb59z7rzflch99cd4rg";
+      type = "gem";
+    };
+    version = "1.2.2";
+  };
+  tilt = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0bmjgbv8158klwp2r3klxjwaj93nh1sbl4xvj9wsha0ic478avz7";
+      type = "gem";
+    };
+    version = "2.2.0";
+  };
+  timeout = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1d9cvm0f4zdpwa795v3zv4973y5zk59j7s1x3yn90jjrhcz1yvfd";
+      type = "gem";
+    };
+    version = "0.4.0";
+  };
+  tzinfo = {
+    dependencies = ["concurrent-ruby"];
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "16w2g84dzaf3z13gxyzlzbf748kylk5bdgg3n1ipvkvvqy685bwd";
+      type = "gem";
+    };
+    version = "2.0.6";
+  };
+  tzinfo-data = {
+    dependencies = ["tzinfo"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0m2d0gpsgqnv29j5h2d6g57g0rayvd460b8s2vjr8sn46bqf89m5";
+      type = "gem";
+    };
+    version = "1.2023.3";
+  };
+  uglifier = {
+    dependencies = ["execjs"];
+    groups = ["assets"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0wgh7bzy68vhv9v68061519dd8samcy8sazzz0w3k8kqpy3g4s5f";
+      type = "gem";
+    };
+    version = "4.2.0";
+  };
+  unf = {
+    dependencies = ["unf_ext"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0bh2cf73i2ffh4fcpdn9ir4mhq8zi50ik0zqa1braahzadx536a9";
+      type = "gem";
+    };
+    version = "0.1.4";
+  };
+  unf_ext = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1yj2nz2l101vr1x9w2k83a0fag1xgnmjwp8w8rw4ik2rwcz65fch";
+      type = "gem";
+    };
+    version = "0.0.8.2";
+  };
+  unicode-display_width = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1gi82k102q7bkmfi7ggn9ciypn897ylln1jk9q67kjhr39fj043a";
+      type = "gem";
+    };
+    version = "2.4.2";
+  };
+  unicorn = {
+    dependencies = ["kgio" "raindrops"];
+    groups = ["default"];
+    platforms = [{
+      engine = "maglev";
+    } {
+      engine = "rbx";
+    } {
+      engine = "ruby";
+    }];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1h0gma14jjxiz6piyi6p99q7lya2mxrq79l03160hascvmx9ipa5";
+      type = "gem";
+    };
+    version = "6.1.0";
+  };
+  uniform_notifier = {
+    groups = ["default" "development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1dfvqixshwvm82b9qwdidvnkavdj7s0fbdbmyd4knkl6l3j9xcwr";
+      type = "gem";
+    };
+    version = "1.16.0";
+  };
+  uri = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0fa49cdssxllj1j37a56kq27wsibx5lmqxkqdk1rz3452y0bsydy";
+      type = "gem";
+    };
+    version = "0.12.2";
+  };
+  version_gem = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0q6zs0wgcrql9671fw6lmbvgh155snaak4fia24iji5wk9klpfh7";
+      type = "gem";
+    };
+    version = "1.1.3";
+  };
+  web-push = {
+    dependencies = ["hkdf" "jwt" "openssl"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1jsximg9v44rpclhjxp03fxk68jx675pghwxc66wj7rn9h9fc54i";
+      type = "gem";
+    };
+    version = "3.0.0";
+  };
+  webdrivers = {
+    dependencies = ["nokogiri" "rubyzip" "selenium-webdriver"];
+    groups = ["test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "19aaxhawzv7315rh285gd1fg6m6wbrn3w3kilyibci1wphgm7mfp";
+      type = "gem";
+    };
+    version = "5.3.1";
+  };
+  webmock = {
+    dependencies = ["addressable" "crack" "hashdiff"];
+    groups = ["test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1myj44wvbbqvv18ragv3ihl0h61acgnfwrnj3lccdgp49bgmbjal";
+      type = "gem";
+    };
+    version = "3.18.1";
+  };
+  websocket = {
+    groups = ["default" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0dib6p55sl606qb4vpwrvj5wh881kk4aqn2zpfapf8ckx7g14jw8";
+      type = "gem";
+    };
+    version = "1.2.9";
+  };
+  xpath = {
+    dependencies = ["nokogiri"];
+    groups = ["default" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0bh8lk9hvlpn7vmi6h4hkcwjzvs2y0cmkk3yjjdr8fxvj6fsgzbd";
+      type = "gem";
+    };
+    version = "3.2.0";
+  };
+  yaml-lint = {
+    groups = ["development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "12jc68af2mwdkr9iqay2v6qgq47yk5g82sd171riibk62wbhp5p3";
+      type = "gem";
+    };
+    version = "0.1.2";
+  };
+  yard = {
+    groups = ["development"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "013yrnwx1zhzhn1fnc19zck22a1qgimsaglp2iwgf5bz9l8h93js";
+      type = "gem";
+    };
+    version = "0.9.34";
+  };
+  zeitwerk = {
+    groups = ["default" "development" "test"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "06vf6y5ai20ry3b1h9cl7vsdj6i5valq172zdxpnfhj5zvlp104j";
+      type = "gem";
+    };
+    version = "2.6.10";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/unicorn_logging_and_timeout.patch b/nixpkgs/pkgs/servers/web-apps/discourse/unicorn_logging_and_timeout.patch
new file mode 100644
index 000000000000..88ebc1337487
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/unicorn_logging_and_timeout.patch
@@ -0,0 +1,25 @@
+diff --git a/config/unicorn.conf.rb b/config/unicorn.conf.rb
+index e69979adfe..68cb04a036 100644
+--- a/config/unicorn.conf.rb
++++ b/config/unicorn.conf.rb
+@@ -27,18 +27,10 @@ pid (ENV["UNICORN_PID_PATH"] || "#{discourse_path}/tmp/pids/unicorn.pid")
+ 
+ if ENV["RAILS_ENV"] != "production"
+   logger Logger.new(STDOUT)
+-  # we want a longer timeout in dev cause first request can be really slow
+-  timeout (ENV["UNICORN_TIMEOUT"] && ENV["UNICORN_TIMEOUT"].to_i || 60)
+-else
+-  # By default, the Unicorn logger will write to stderr.
+-  # Additionally, some applications/frameworks log to stderr or stdout,
+-  # so prevent them from going to /dev/null when daemonized here:
+-  stderr_path "#{discourse_path}/log/unicorn.stderr.log"
+-  stdout_path "#{discourse_path}/log/unicorn.stdout.log"
+-  # nuke workers after 30 seconds instead of 60 seconds (the default)
+-  timeout 30
+ end
+ 
++timeout (ENV["UNICORN_TIMEOUT"] && ENV["UNICORN_TIMEOUT"].to_i || 60)
++
+ # important for Ruby 2.0
+ preload_app true
+ 
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/update.py b/nixpkgs/pkgs/servers/web-apps/discourse/update.py
new file mode 100755
index 000000000000..9b300d1d4959
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/update.py
@@ -0,0 +1,441 @@
+#!/usr/bin/env nix-shell
+#! nix-shell -i python3 -p bundix bundler nix-update nix-universal-prefetch python3 python3Packages.requests python3Packages.click python3Packages.click-log prefetch-yarn-deps
+from __future__ import annotations
+
+import click
+import click_log
+import shutil
+import tempfile
+import re
+import logging
+import subprocess
+import os
+import stat
+import json
+import requests
+import textwrap
+from functools import total_ordering
+from distutils.version import LooseVersion
+from itertools import zip_longest
+from pathlib import Path
+from typing import Union, Iterable
+
+
+logger = logging.getLogger(__name__)
+
+
+@total_ordering
+class DiscourseVersion:
+    """Represents a Discourse style version number and git tag.
+
+    This takes either a tag or version string as input and
+    extrapolates the other. Sorting is implemented to work as expected
+    in regard to A.B.C.betaD version numbers - 2.0.0.beta1 is
+    considered lower than 2.0.0.
+
+    """
+
+    tag: str = ""
+    version: str = ""
+    split_version: Iterable[Union[None, int, str]] = []
+
+    def __init__(self, version: str):
+        """Take either a tag or version number, calculate the other."""
+        if version.startswith('v'):
+            self.tag = version
+            self.version = version.lstrip('v')
+        else:
+            self.tag = 'v' + version
+            self.version = version
+        self.split_version = LooseVersion(self.version).version
+
+    def __eq__(self, other: DiscourseVersion):
+        """Versions are equal when their individual parts are."""
+        return self.split_version == other.split_version
+
+    def __gt__(self, other: DiscourseVersion):
+        """Check if this version is greater than the other.
+
+        Goes through the parts of the version numbers from most to
+        least significant, only continuing on to the next if the
+        numbers are equal and no decision can be made. If one version
+        ends in 'betaX' and the other doesn't, all else being equal,
+        the one without 'betaX' is considered greater, since it's the
+        release version.
+
+        """
+        for (this_ver, other_ver) in zip_longest(self.split_version, other.split_version):
+            if this_ver == other_ver:
+                continue
+            if type(this_ver) is int and type(other_ver) is int:
+                return this_ver > other_ver
+            elif 'beta' in [this_ver, other_ver]:
+                # release version (None) is greater than beta
+                return this_ver is None
+        else:
+            return False
+
+
+class DiscourseRepo:
+    version_regex = re.compile(r'^v\d+\.\d+\.\d+(\.beta\d+)?$')
+    _latest_commit_sha = None
+
+    def __init__(self, owner: str = 'discourse', repo: str = 'discourse'):
+        self.owner = owner
+        self.repo = repo
+
+    @property
+    def versions(self) -> Iterable[str]:
+        r = requests.get(f'https://api.github.com/repos/{self.owner}/{self.repo}/git/refs/tags').json()
+        tags = [x['ref'].replace('refs/tags/', '') for x in r]
+
+        # filter out versions not matching version_regex
+        versions = filter(self.version_regex.match, tags)
+        versions = [DiscourseVersion(x) for x in versions]
+        versions.sort(reverse=True)
+        return versions
+
+    @property
+    def latest_commit_sha(self) -> str:
+        if self._latest_commit_sha is None:
+            r = requests.get(f'https://api.github.com/repos/{self.owner}/{self.repo}/commits?per_page=1')
+            r.raise_for_status()
+            self._latest_commit_sha = r.json()[0]['sha']
+
+        return self._latest_commit_sha
+
+    def get_yarn_lock_hash(self, rev: str):
+        yarnLockText = self.get_file('app/assets/javascripts/yarn.lock', rev)
+        with tempfile.NamedTemporaryFile(mode='w') as lockFile:
+            lockFile.write(yarnLockText)
+            return subprocess.check_output(['prefetch-yarn-deps', lockFile.name]).decode('utf-8').strip()
+
+    def get_file(self, filepath, rev):
+        """Return file contents at a given rev.
+
+        :param str filepath: the path to the file, relative to the repo root
+        :param str rev: the rev to fetch at :return:
+
+        """
+        r = requests.get(f'https://raw.githubusercontent.com/{self.owner}/{self.repo}/{rev}/{filepath}')
+        r.raise_for_status()
+        return r.text
+
+
+def _call_nix_update(pkg, version):
+    """Call nix-update from nixpkgs root dir."""
+    nixpkgs_path = Path(__file__).parent / '../../../../'
+    return subprocess.check_output(['nix-update', pkg, '--version', version], cwd=nixpkgs_path)
+
+
+def _nix_eval(expr: str):
+    nixpkgs_path = Path(__file__).parent / '../../../../'
+    try:
+        output = subprocess.check_output(['nix-instantiate', '--strict', '--json', '--eval', '-E', f'(with import {nixpkgs_path} {{}}; {expr})'], text=True)
+    except subprocess.CalledProcessError:
+        return None
+    return json.loads(output)
+
+
+def _get_current_package_version(pkg: str):
+    return _nix_eval(f'{pkg}.version')
+
+
+def _diff_file(filepath: str, old_version: DiscourseVersion, new_version: DiscourseVersion):
+    repo = DiscourseRepo()
+
+    current_dir = Path(__file__).parent
+
+    old = repo.get_file(filepath, old_version.tag)
+    new = repo.get_file(filepath, new_version.tag)
+
+    if old == new:
+        click.secho(f'{filepath} is unchanged', fg='green')
+        return
+
+    with tempfile.NamedTemporaryFile(mode='w') as o, tempfile.NamedTemporaryFile(mode='w') as n:
+        o.write(old), n.write(new)
+        width = shutil.get_terminal_size((80, 20)).columns
+        diff_proc = subprocess.run(
+            ['diff', '--color=always', f'--width={width}', '-y', o.name, n.name],
+            stdout=subprocess.PIPE,
+            cwd=current_dir,
+            text=True
+        )
+
+    click.secho(f'Diff for {filepath} ({old_version.version} -> {new_version.version}):', fg='bright_blue', bold=True)
+    click.echo(diff_proc.stdout + '\n')
+    return
+
+
+def _remove_platforms(rubyenv_dir: Path):
+    for platform in ['arm64-darwin-20', 'x86_64-darwin-18',
+                     'x86_64-darwin-19', 'x86_64-darwin-20',
+                     'x86_64-linux', 'aarch64-linux']:
+        with open(rubyenv_dir / 'Gemfile.lock', 'r') as f:
+            for line in f:
+                if platform in line:
+                    subprocess.check_output(
+                        ['bundle', 'lock', '--remove-platform', platform], cwd=rubyenv_dir)
+                    break
+
+
+@click_log.simple_verbosity_option(logger)
+
+
+@click.group()
+def cli():
+    pass
+
+
+@cli.command()
+@click.argument('rev', default='latest')
+@click.option('--reverse/--no-reverse', default=False, help='Print diffs from REV to current.')
+def print_diffs(rev, reverse):
+    """Print out diffs for files used as templates for the NixOS module.
+
+    The current package version found in the nixpkgs worktree the
+    script is run from will be used to download the "from" file and
+    REV used to download the "to" file for the diff, unless the
+    '--reverse' flag is specified.
+
+    REV should be the git rev to find changes in ('vX.Y.Z') or
+    'latest'; defaults to 'latest'.
+
+    """
+    if rev == 'latest':
+        repo = DiscourseRepo()
+        rev = repo.versions[0].tag
+
+    old_version = DiscourseVersion(_get_current_package_version('discourse'))
+    new_version = DiscourseVersion(rev)
+
+    if reverse:
+        old_version, new_version = new_version, old_version
+
+    for f in ['config/nginx.sample.conf', 'config/discourse_defaults.conf']:
+        _diff_file(f, old_version, new_version)
+
+
+@cli.command()
+@click.argument('rev', default='latest')
+def update(rev):
+    """Update gem files and version.
+
+    REV: the git rev to update to ('vX.Y.Z[.betaA]') or
+    'latest'; defaults to 'latest'.
+
+    """
+    repo = DiscourseRepo()
+
+    if rev == 'latest':
+        version = repo.versions[0]
+    else:
+        version = DiscourseVersion(rev)
+
+    logger.debug(f"Using rev {version.tag}")
+    logger.debug(f"Using version {version.version}")
+
+    rubyenv_dir = Path(__file__).parent / "rubyEnv"
+
+    for fn in ['Gemfile.lock', 'Gemfile']:
+        with open(rubyenv_dir / fn, 'w') as f:
+            f.write(repo.get_file(fn, version.tag))
+
+    subprocess.check_output(['bundle', 'lock'], cwd=rubyenv_dir)
+    _remove_platforms(rubyenv_dir)
+    subprocess.check_output(['bundix'], cwd=rubyenv_dir)
+
+    _call_nix_update('discourse', version.version)
+
+    old_yarn_hash = _nix_eval('discourse.assets.yarnOfflineCache.outputHash')
+    new_yarn_hash = repo.get_yarn_lock_hash(version.tag)
+    click.echo(f"Updating yarn lock hash, {old_yarn_hash} -> {new_yarn_hash}")
+    with open(Path(__file__).parent / "default.nix", 'r+') as f:
+        content = f.read()
+        content = content.replace(old_yarn_hash, new_yarn_hash)
+        f.seek(0)
+        f.write(content)
+        f.truncate()
+
+
+@cli.command()
+@click.argument('rev', default='latest')
+def update_mail_receiver(rev):
+    """Update discourse-mail-receiver.
+
+    REV: the git rev to update to ('vX.Y.Z') or 'latest'; defaults to
+    'latest'.
+
+    """
+    repo = DiscourseRepo(repo="mail-receiver")
+
+    if rev == 'latest':
+        version = repo.versions[0]
+    else:
+        version = DiscourseVersion(rev)
+
+    _call_nix_update('discourse-mail-receiver', version.version)
+
+
+@cli.command()
+def update_plugins():
+    """Update plugins to their latest revision."""
+    plugins = [
+        {'name': 'discourse-assign'},
+        {'name': 'discourse-bbcode-color'},
+        {'name': 'discourse-calendar'},
+        {'name': 'discourse-canned-replies'},
+        {'name': 'discourse-chat-integration'},
+        {'name': 'discourse-checklist'},
+        {'name': 'discourse-data-explorer'},
+        {'name': 'discourse-docs'},
+        {'name': 'discourse-github'},
+        {'name': 'discourse-ldap-auth', 'owner': 'jonmbake'},
+        {'name': 'discourse-math'},
+        {'name': 'discourse-migratepassword', 'owner': 'discoursehosting'},
+        {'name': 'discourse-openid-connect'},
+        {'name': 'discourse-prometheus'},
+        {'name': 'discourse-reactions'},
+        {'name': 'discourse-saved-searches'},
+        {'name': 'discourse-solved'},
+        {'name': 'discourse-spoiler-alert'},
+        {'name': 'discourse-voting'},
+        {'name': 'discourse-yearly-review'},
+    ]
+
+    for plugin in plugins:
+        fetcher = plugin.get('fetcher') or "fetchFromGitHub"
+        owner = plugin.get('owner') or "discourse"
+        name = plugin.get('name')
+        repo_name = plugin.get('repo_name') or name
+
+        repo = DiscourseRepo(owner=owner, repo=repo_name)
+
+        # implement the plugin pinning algorithm laid out here:
+        # https://meta.discourse.org/t/pinning-plugin-and-theme-versions-for-older-discourse-installs/156971
+        # this makes sure we don't upgrade plugins to revisions that
+        # are incompatible with the packaged Discourse version
+        try:
+            compatibility_spec = repo.get_file('.discourse-compatibility', repo.latest_commit_sha)
+            versions = [(DiscourseVersion(discourse_version), plugin_rev.strip(' '))
+                        for [discourse_version, plugin_rev]
+                        in [line.split(':')
+                            for line
+                            in compatibility_spec.splitlines() if line != '']]
+            discourse_version = DiscourseVersion(_get_current_package_version('discourse'))
+            versions = list(filter(lambda ver: ver[0] >= discourse_version, versions))
+            if versions == []:
+                rev = repo.latest_commit_sha
+            else:
+                rev = versions[0][1]
+                print(rev)
+        except requests.exceptions.HTTPError:
+            rev = repo.latest_commit_sha
+
+        filename = _nix_eval(f'builtins.unsafeGetAttrPos "src" discourse.plugins.{name}')
+        if filename is None:
+            filename = Path(__file__).parent / 'plugins' / name / 'default.nix'
+            filename.parent.mkdir()
+
+            has_ruby_deps = False
+            for line in repo.get_file('plugin.rb', rev).splitlines():
+                if 'gem ' in line:
+                    has_ruby_deps = True
+                    break
+
+            with open(filename, 'w') as f:
+                f.write(textwrap.dedent(f"""
+                         {{ lib, mkDiscoursePlugin, fetchFromGitHub }}:
+
+                         mkDiscoursePlugin {{
+                           name = "{name}";"""[1:] + ("""
+                           bundlerEnvArgs.gemdir = ./.;""" if has_ruby_deps else "") + f"""
+                           src = {fetcher} {{
+                             owner = "{owner}";
+                             repo = "{repo_name}";
+                             rev = "replace-with-git-rev";
+                             sha256 = "replace-with-sha256";
+                           }};
+                           meta = with lib; {{
+                             homepage = "";
+                             maintainers = with maintainers; [ ];
+                             license = licenses.mit; # change to the correct license!
+                             description = "";
+                           }};
+                         }}"""))
+
+            all_plugins_filename = Path(__file__).parent / 'plugins' / 'all-plugins.nix'
+            with open(all_plugins_filename, 'r+') as f:
+                content = f.read()
+                pos = -1
+                while content[pos] != '}':
+                    pos -= 1
+                content = content[:pos] + f'  {name} = callPackage ./{name} {{}};' + os.linesep + content[pos:]
+                f.seek(0)
+                f.write(content)
+                f.truncate()
+
+        else:
+            filename = filename['file']
+
+        prev_commit_sha = _nix_eval(f'discourse.plugins.{name}.src.rev')
+
+        if prev_commit_sha == rev:
+            click.echo(f'Plugin {name} is already at the latest revision')
+            continue
+
+        prev_hash = _nix_eval(f'discourse.plugins.{name}.src.outputHash')
+        new_hash = subprocess.check_output([
+            'nix-universal-prefetch', fetcher,
+            '--owner', owner,
+            '--repo', repo_name,
+            '--rev', rev,
+        ], text=True).strip("\n")
+
+        click.echo(f"Update {name}, {prev_commit_sha} -> {rev} in {filename}")
+
+        with open(filename, 'r+') as f:
+            content = f.read()
+            content = content.replace(prev_commit_sha, rev)
+            content = content.replace(prev_hash, new_hash)
+            f.seek(0)
+            f.write(content)
+            f.truncate()
+
+        rubyenv_dir = Path(filename).parent
+        gemfile = rubyenv_dir / "Gemfile"
+        version_file_regex = re.compile(r'.*File\.expand_path\("\.\./(.*)", __FILE__\)')
+        gemfile_text = ''
+        plugin_file = repo.get_file('plugin.rb', rev)
+        plugin_file = plugin_file.replace(",\n", ", ") # fix split lines
+        for line in plugin_file.splitlines():
+            if 'gem ' in line:
+                line = ','.join(filter(lambda x: ":require_name" not in x, line.split(',')))
+                gemfile_text = gemfile_text + line + os.linesep
+
+                version_file_match = version_file_regex.match(line)
+                if version_file_match is not None:
+                    filename = version_file_match.groups()[0]
+                    content = repo.get_file(filename, rev)
+                    with open(rubyenv_dir / filename, 'w') as f:
+                        f.write(content)
+
+        if len(gemfile_text) > 0:
+            if os.path.isfile(gemfile):
+                os.remove(gemfile)
+
+            subprocess.check_output(['bundle', 'init'], cwd=rubyenv_dir)
+            os.chmod(gemfile, stat.S_IREAD | stat.S_IWRITE | stat.S_IRGRP | stat.S_IROTH)
+
+            with open(gemfile, 'a') as f:
+                f.write(gemfile_text)
+
+            subprocess.check_output(['bundle', 'lock', '--add-platform', 'ruby'], cwd=rubyenv_dir)
+            subprocess.check_output(['bundle', 'lock', '--update'], cwd=rubyenv_dir)
+            _remove_platforms(rubyenv_dir)
+            subprocess.check_output(['bundix'], cwd=rubyenv_dir)
+
+
+if __name__ == '__main__':
+    cli()
diff --git a/nixpkgs/pkgs/servers/web-apps/discourse/use_mv_instead_of_rename.patch b/nixpkgs/pkgs/servers/web-apps/discourse/use_mv_instead_of_rename.patch
new file mode 100644
index 000000000000..30493b543e38
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/discourse/use_mv_instead_of_rename.patch
@@ -0,0 +1,22 @@
+diff --git a/lib/discourse.rb b/lib/discourse.rb
+index ea2a3cbafd..66454d9157 100644
+--- a/lib/discourse.rb
++++ b/lib/discourse.rb
+@@ -62,7 +62,7 @@ module Discourse
+         fd.fsync()
+       end
+ 
+-      File.rename(temp_destination, destination)
++      FileUtils.mv(temp_destination, destination)
+ 
+       nil
+     end
+@@ -76,7 +76,7 @@ module Discourse
+       FileUtils.mkdir_p(File.join(Rails.root, 'tmp'))
+       temp_destination = File.join(Rails.root, 'tmp', SecureRandom.hex)
+       execute_command('ln', '-s', source, temp_destination)
+-      File.rename(temp_destination, destination)
++      FileUtils.mv(temp_destination, destination)
+ 
+       nil
+     end
diff --git a/nixpkgs/pkgs/servers/web-apps/dokuwiki/default.nix b/nixpkgs/pkgs/servers/web-apps/dokuwiki/default.nix
new file mode 100644
index 000000000000..00cbbfd0ad24
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/dokuwiki/default.nix
@@ -0,0 +1,91 @@
+{ lib
+, stdenv
+, fetchFromGitHub
+, writeText
+, nixosTests
+, dokuwiki
+}:
+
+stdenv.mkDerivation rec {
+  pname = "dokuwiki";
+  version = "2024-02-06a";
+
+  src = fetchFromGitHub {
+    owner = "dokuwiki";
+    repo = pname;
+    rev = "release-${version}";
+    sha256 = "sha256-gAoEUskTTbcpHgDUBSsAv6QQDvPuxQ1jXZ4TTKrjWIU=";
+  };
+
+  preload = writeText "preload.php" ''
+  <?php
+
+    $config_cascade = array(
+      'acl' => array(
+        'default'   => getenv('DOKUWIKI_ACL_AUTH_CONFIG'),
+      ),
+      'plainauth.users' => array(
+        'default'   => getenv('DOKUWIKI_USERS_AUTH_CONFIG'),
+        'protected' => "" // not used by default
+      ),
+    );
+  '';
+
+  phpLocalConfig = writeText "local.php" ''
+  <?php
+    return require(getenv('DOKUWIKI_LOCAL_CONFIG'));
+  ?>
+  '';
+
+  phpPluginsLocalConfig = writeText "plugins.local.php" ''
+  <?php
+    return require(getenv('DOKUWIKI_PLUGINS_LOCAL_CONFIG'));
+  ?>
+  '';
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir -p $out/share/dokuwiki
+    cp -r * $out/share/dokuwiki
+    cp ${preload} $out/share/dokuwiki/inc/preload.php
+    cp ${phpLocalConfig} $out/share/dokuwiki/conf/local.php
+    cp ${phpPluginsLocalConfig} $out/share/dokuwiki/conf/plugins.local.php
+
+    runHook postInstall
+  '';
+
+  passthru = {
+    combine = { basePackage ? dokuwiki
+      , plugins ? []
+      , templates ? []
+      , localConfig ? null
+      , pluginsConfig ? null
+      , aclConfig ? null
+      , pname ? (p: "${p.pname}-combined")
+    }: let
+      isNotEmpty = x: lib.optionalString (! builtins.elem x [ null "" ]);
+    in basePackage.overrideAttrs (prev: {
+      pname = if builtins.isFunction pname then pname prev else pname;
+
+      postInstall = prev.postInstall or "" + ''
+        ${lib.concatMapStringsSep "\n" (tpl: "cp -r ${toString tpl} $out/share/dokuwiki/lib/tpl/${tpl.name}") templates}
+        ${lib.concatMapStringsSep "\n" (plugin: "cp -r ${toString plugin} $out/share/dokuwiki/lib/plugins/${plugin.name}") plugins}
+        ${isNotEmpty localConfig "ln -sf ${localConfig} $out/share/dokuwiki/conf/local.php" }
+        ${isNotEmpty pluginsConfig "ln -sf ${pluginsConfig} $out/share/dokuwiki/conf/plugins.local.php" }
+        ${isNotEmpty aclConfig "ln -sf ${aclConfig} $out/share/dokuwiki/acl.auth.php" }
+      '';
+    });
+    tests = {
+      inherit (nixosTests) dokuwiki;
+    };
+  };
+
+  meta = with lib; {
+    description = "Simple to use and highly versatile Open Source wiki software that doesn't require a database";
+    license = licenses.gpl2;
+    homepage = "https://www.dokuwiki.org";
+    platforms = platforms.all;
+    maintainers = with maintainers; [ _1000101 ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/dolibarr/default.nix b/nixpkgs/pkgs/servers/web-apps/dolibarr/default.nix
new file mode 100644
index 000000000000..fa6abf047943
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/dolibarr/default.nix
@@ -0,0 +1,41 @@
+{ stdenv, lib, fetchFromGitHub, nixosTests, stateDir ? "/var/lib/dolibarr" }:
+
+stdenv.mkDerivation rec {
+  pname = "dolibarr";
+  version = "19.0.0";
+
+  src = fetchFromGitHub {
+    owner = "Dolibarr";
+    repo = "dolibarr";
+    rev = version;
+    hash = "sha256-Guq3CHdVqGfprXo0O3VriWSfWR/sIgj3Znso1BUeLNY=";
+  };
+
+  dontBuild = true;
+
+  postPatch = ''
+    find . -type f -name "*.php" -print0 | xargs -0 sed -i 's|/etc/dolibarr|${stateDir}|g'
+
+    substituteInPlace htdocs/filefunc.inc.php \
+      --replace '//$conffile = ' '$conffile = ' \
+      --replace '//$conffiletoshow = ' '$conffiletoshow = '
+
+    substituteInPlace htdocs/install/inc.php \
+      --replace '//$conffile = ' '$conffile = ' \
+      --replace '//$conffiletoshow = ' '$conffiletoshow = '
+  '';
+
+  installPhase = ''
+    mkdir -p "$out"
+    cp -r * $out
+  '';
+
+  passthru.tests = { inherit (nixosTests) dolibarr; };
+
+  meta = with lib; {
+    description = "A enterprise resource planning (ERP) and customer relationship manager (CRM) server";
+    homepage = "https://dolibarr.org/";
+    license = licenses.gpl3Plus;
+    maintainers = [ ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/engelsystem/default.nix b/nixpkgs/pkgs/servers/web-apps/engelsystem/default.nix
new file mode 100644
index 000000000000..4f6563db90b7
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/engelsystem/default.nix
@@ -0,0 +1,53 @@
+{ lib
+, fetchzip
+, nixosTests
+, php
+, stdenv
+, writeText
+}:
+
+stdenv.mkDerivation rec {
+  pname = "engelsystem";
+  version = "3.5.0";
+
+  src = fetchzip {
+    url = "https://github.com/engelsystem/engelsystem/releases/download/v${version}/engelsystem-v${version}.zip";
+    hash = "sha256-RbzAHBZN02u14WaLtq5EOh4XwIdHKvzX7NhDBhn/CaU=";
+  };
+
+  buildInputs = [ php ];
+
+  installPhase = ''
+    runHook preInstall
+
+    # prepare
+    rm -r ./storage/
+
+    ln -sf /etc/engelsystem/config.php ./config/config.php
+    ln -sf /var/lib/engelsystem/storage/ ./storage
+
+    mkdir -p $out/share/engelsystem
+    mkdir -p $out/bin
+    cp -r . $out/share/engelsystem
+
+    echo $(command -v php)
+    # The patchShebangAuto function always used the php without extensions, so path the shebang manually
+    sed -i -e "1 s|.*|#\!${lib.getExe php}|" "$out/share/engelsystem/bin/migrate"
+    ln -s "$out/share/engelsystem/bin/migrate" "$out/bin/migrate"
+
+    runHook postInstall
+  '';
+
+  passthru.tests = nixosTests.engelsystem;
+
+  meta = with lib; {
+    changelog = "https://github.com/engelsystem/engelsystem/releases/tag/v${version}";
+    description =
+      "Coordinate your volunteers in teams, assign them to work shifts or let them decide for themselves when and where they want to help with what";
+    homepage = "https://engelsystem.de";
+    license = licenses.gpl2;
+    mainProgram = "migrate";
+    maintainers = with maintainers; [ ];
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/ethercalc/default.nix b/nixpkgs/pkgs/servers/web-apps/ethercalc/default.nix
new file mode 100644
index 000000000000..9c7e160e6c42
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/ethercalc/default.nix
@@ -0,0 +1,27 @@
+{ stdenv
+, pkgs
+, lib
+, nodejs_20
+}:
+
+let
+  nodejs = nodejs_20;
+
+  nodePackages = import ./node-packages.nix {
+    inherit pkgs nodejs;
+    inherit (stdenv.hostPlatform) system;
+  };
+
+  ethercalc = lib.head (lib.attrValues nodePackages);
+
+  combined = ethercalc.override {
+    meta = with lib; {
+      description = "Online collaborative spreadsheet";
+      license = with licenses; [ cpal10 artistic2 mit asl20 cc0 mpl20 ];
+      homepage = "https://github.com/audreyt/ethercalc";
+      maintainers = with maintainers; [ iblech ];
+      platforms = platforms.unix;
+    };
+  };
+in
+  combined
diff --git a/nixpkgs/pkgs/servers/web-apps/ethercalc/generate.sh b/nixpkgs/pkgs/servers/web-apps/ethercalc/generate.sh
new file mode 100755
index 000000000000..d87c9b93966b
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/ethercalc/generate.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env nix-shell
+#! nix-shell -i bash -p nodePackages.node2nix
+
+# Run this script not via `./generate.sh`, but via `$PWD/generate.sh`.
+# Else `nix-shell` will not find this script.
+
+set -euo pipefail
+
+cd -- "$(dirname -- "$BASH_SOURCE[0]")"
+
+node2nix \
+     --nodejs-14 \
+     --input node-packages.json \
+     --output node-packages-generated.nix \
+     --composition node-packages.nix \
+     --node-env ../../../development/node-packages/node-env.nix
diff --git a/nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages-generated.nix b/nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages-generated.nix
new file mode 100644
index 000000000000..3baba4ac727a
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages-generated.nix
@@ -0,0 +1,2053 @@
+# This file has been generated by node2nix 1.11.1. Do not edit!
+
+{nodeEnv, fetchurl, fetchgit, nix-gitignore, stdenv, lib, globalBuildInputs ? []}:
+
+let
+  sources = {
+    "accepts-1.0.7" = {
+      name = "accepts";
+      packageName = "accepts";
+      version = "1.0.7";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/accepts/-/accepts-1.0.7.tgz";
+        sha512 = "iq8ew2zitUlNcUca0wye3fYwQ6sSPItDo38oC0R+XA5KTzeXRN+GF7NjOXs3dVItj4J+gQVdpq4/qbnMb1hMHw==";
+      };
+    };
+    "adler-32-1.0.0" = {
+      name = "adler-32";
+      packageName = "adler-32";
+      version = "1.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/adler-32/-/adler-32-1.0.0.tgz";
+        sha512 = "kH0TVBEB75TEziSFdX+ot2jbdq52OOA4eWQSv9KVx6U4Y3eg8uebS0Zw3hszufidzA733WcAgA6BzFBw/L2cfw==";
+      };
+    };
+    "adler-32-1.2.0" = {
+      name = "adler-32";
+      packageName = "adler-32";
+      version = "1.2.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz";
+        sha512 = "/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==";
+      };
+    };
+    "adler-32-1.3.1" = {
+      name = "adler-32";
+      packageName = "adler-32";
+      version = "1.3.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz";
+        sha512 = "ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==";
+      };
+    };
+    "after-0.8.1" = {
+      name = "after";
+      packageName = "after";
+      version = "0.8.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/after/-/after-0.8.1.tgz";
+        sha512 = "SuI3vWhCFeSmkmmJ3efyuOkrhGyp/AuHthh3F5DinGYh2kR9t/0xUlm3/Vn2qMScfgg+cKho5fW7TUEYUhYeiA==";
+      };
+    };
+    "amdefine-1.0.1" = {
+      name = "amdefine";
+      packageName = "amdefine";
+      version = "1.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz";
+        sha512 = "S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==";
+      };
+    };
+    "any-promise-1.3.0" = {
+      name = "any-promise";
+      packageName = "any-promise";
+      version = "1.3.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz";
+        sha512 = "7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==";
+      };
+    };
+    "arraybuffer.slice-0.0.6" = {
+      name = "arraybuffer.slice";
+      packageName = "arraybuffer.slice";
+      version = "0.0.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz";
+        sha512 = "6ZjfQaBSy6CuIH0+B0NrxMfDE5VIOCP/5gOqSpEIsaAZx9/giszzrXg6PZ7G51U/n88UmlAgYLNQ9wAnII7PJA==";
+      };
+    };
+    "async-0.2.10" = {
+      name = "async";
+      packageName = "async";
+      version = "0.2.10";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/async/-/async-0.2.10.tgz";
+        sha512 = "eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==";
+      };
+    };
+    "babyparse-0.2.1" = {
+      name = "babyparse";
+      packageName = "babyparse";
+      version = "0.2.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/babyparse/-/babyparse-0.2.1.tgz";
+        sha512 = "94zhgPYkWLpOCB8BkGyGkXNFCBh0TsRWBGmmoXvR8imRe/hQiLIm0V5zVoKPKIjQ8y52hKtFchiPxJcz1QaH5Q==";
+      };
+    };
+    "balanced-match-1.0.2" = {
+      name = "balanced-match";
+      packageName = "balanced-match";
+      version = "1.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz";
+        sha512 = "3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==";
+      };
+    };
+    "base64-arraybuffer-0.1.2" = {
+      name = "base64-arraybuffer";
+      packageName = "base64-arraybuffer";
+      version = "0.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz";
+        sha512 = "ewBKKVVPIl78B26mYQHYlaxR7NydMiD/GxwLNIwTAfLIE4xhN2Gxcy30//azq5UrejXjzGpWjcBu3NUJxzMMzg==";
+      };
+    };
+    "base64-url-1.2.1" = {
+      name = "base64-url";
+      packageName = "base64-url";
+      version = "1.2.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz";
+        sha512 = "V8E0l1jyyeSSS9R+J9oljx5eq2rqzClInuwaPcyuv0Mm3ViI/3/rcc4rCEO8i4eQ4I0O0FAGYDA2i5xWHHPhzg==";
+      };
+    };
+    "base64id-0.1.0" = {
+      name = "base64id";
+      packageName = "base64id";
+      version = "0.1.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz";
+        sha512 = "DSjtfjhAsHl9J4OJj7e4+toV2zqxJrGwVd3CLlsCp8QmicvOn7irG0Mb8brOc/nur3SdO8lIbNlY1s1ZDJdUKQ==";
+      };
+    };
+    "basic-auth-1.0.0" = {
+      name = "basic-auth";
+      packageName = "basic-auth";
+      version = "1.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.0.tgz";
+        sha512 = "qzxS7/bW/LSiKZzdZw3isPjiVmzXbJLM3ImZZ62WMR3oJQAyqy094Nnb0TA2ZZm65xB7nu0acfTQ99z7wwCDCw==";
+      };
+    };
+    "basic-auth-connect-1.0.0" = {
+      name = "basic-auth-connect";
+      packageName = "basic-auth-connect";
+      version = "1.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz";
+        sha512 = "kiV+/DTgVro4aZifY/hwRwALBISViL5NP4aReaR2EVJEObpbUBHIkdJh/YpcoEiYt7nBodZ6U2ajZeZvSxUCCg==";
+      };
+    };
+    "batch-0.5.1" = {
+      name = "batch";
+      packageName = "batch";
+      version = "0.5.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/batch/-/batch-0.5.1.tgz";
+        sha512 = "OXRjc65VJvFtb7JD5HszSI1WWwsI6YnJS7Qmlx1CaDQrZ5urNIeRjtTyBe1YapNXyoWzrcc4yqg4rNe8YMyong==";
+      };
+    };
+    "better-assert-1.0.2" = {
+      name = "better-assert";
+      packageName = "better-assert";
+      version = "1.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz";
+        sha512 = "bYeph2DFlpK1XmGs6fvlLRUN29QISM3GBuUwSFsMY2XRx4AvC0WNCS57j4c/xGrK2RS24C1w3YoBOsw9fT46tQ==";
+      };
+    };
+    "blob-0.0.2" = {
+      name = "blob";
+      packageName = "blob";
+      version = "0.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/blob/-/blob-0.0.2.tgz";
+        sha512 = "BoCcDt8zBGShn6DawAGQw37s9SSs+fEjiZWDzyB+841PbOogcR2X7LGlM4sR3Zsiq/zoyl8MFWDfN6oDSlveBQ==";
+      };
+    };
+    "body-parser-1.6.7" = {
+      name = "body-parser";
+      packageName = "body-parser";
+      version = "1.6.7";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/body-parser/-/body-parser-1.6.7.tgz";
+        sha512 = "J6HSnbgUPZMhDuqsTyGdpEy6PavO/05c7bKpqXVbYnLUBdH9oM1DvMTC27I3x9F0/tjfvbpuyedP/uUinj+Veg==";
+      };
+    };
+    "brace-expansion-2.0.1" = {
+      name = "brace-expansion";
+      packageName = "brace-expansion";
+      version = "2.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz";
+        sha512 = "XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==";
+      };
+    };
+    "buffer-crc32-0.2.3" = {
+      name = "buffer-crc32";
+      packageName = "buffer-crc32";
+      version = "0.2.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.3.tgz";
+        sha512 = "HLvoSqq1z8fJEcT1lUlJZ4OJaXJZ1wsWm0+fBxkz9Bdf/WphA4Da7FtGUguNNyEXL4WB0hNMTaWmdFRFPy8YOQ==";
+      };
+    };
+    "buffer-from-1.1.2" = {
+      name = "buffer-from";
+      packageName = "buffer-from";
+      version = "1.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz";
+        sha512 = "E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==";
+      };
+    };
+    "bytes-1.0.0" = {
+      name = "bytes";
+      packageName = "bytes";
+      version = "1.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz";
+        sha512 = "/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ==";
+      };
+    };
+    "callsite-1.0.0" = {
+      name = "callsite";
+      packageName = "callsite";
+      version = "1.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz";
+        sha512 = "0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==";
+      };
+    };
+    "cfb-0.11.1" = {
+      name = "cfb";
+      packageName = "cfb";
+      version = "0.11.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/cfb/-/cfb-0.11.1.tgz";
+        sha512 = "1GEqpcO365hTRpP+GzHXNiUF5SB7qmY5aVYwrJm8ISx27HzHpaFlTQhnOCMNhqP0WPkHR0OGE9WDSqtksV4anw==";
+      };
+    };
+    "cfb-1.2.2" = {
+      name = "cfb";
+      packageName = "cfb";
+      version = "1.2.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz";
+        sha512 = "KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==";
+      };
+    };
+    "codepage-1.14.0" = {
+      name = "codepage";
+      packageName = "codepage";
+      version = "1.14.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz";
+        sha512 = "iz3zJLhlrg37/gYRWgEPkaFTtzmnEv1h+r7NgZum2lFElYQPi0/5bnmuDfODHxfp0INEfnRqyfyeIJDbb7ahRw==";
+      };
+    };
+    "codepage-1.8.1" = {
+      name = "codepage";
+      packageName = "codepage";
+      version = "1.8.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/codepage/-/codepage-1.8.1.tgz";
+        sha512 = "9Rag9MN+JZzmzpXI7Pl46F8Es7NLWnR2ymnaCmXWY3+IHREBRnIZWu9DfOkocSKSt3/nX8HzJr5KMi+ck72BgQ==";
+      };
+    };
+    "coffee-css-0.0.5" = {
+      name = "coffee-css";
+      packageName = "coffee-css";
+      version = "0.0.5";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/coffee-css/-/coffee-css-0.0.5.tgz";
+        sha512 = "+mXlsG4GhTh8jEOlIy8VcRrqdsdPbW7Zi4wsg2VTScb4UaDvW1e2UhFEFAQfkyOyrPZXezFcr6vexmysng5lig==";
+      };
+    };
+    "coffee-script-1.12.7" = {
+      name = "coffee-script";
+      packageName = "coffee-script";
+      version = "1.12.7";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz";
+        sha512 = "fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==";
+      };
+    };
+    "coffeecup-0.3.21" = {
+      name = "coffeecup";
+      packageName = "coffeecup";
+      version = "0.3.21";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/coffeecup/-/coffeecup-0.3.21.tgz";
+        sha512 = "FdEt/iFwXCiZ4BMm3+bgrrOx+ixGsYEnpG1lDd51ijugFZDjmNioXdjOcA7P1At5hwLTjuAUZ2envLY8R9Z19A==";
+      };
+    };
+    "colors-0.6.2" = {
+      name = "colors";
+      packageName = "colors";
+      version = "0.6.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz";
+        sha512 = "OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw==";
+      };
+    };
+    "commander-0.6.1" = {
+      name = "commander";
+      packageName = "commander";
+      version = "0.6.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz";
+        sha512 = "0fLycpl1UMTGX257hRsu/arL/cUbcvQM4zMKwvLvzXtfdezIV4yotPS2dYtknF+NmEfWSoCEF6+hj9XLm/6hEw==";
+      };
+    };
+    "commander-1.3.2" = {
+      name = "commander";
+      packageName = "commander";
+      version = "1.3.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/commander/-/commander-1.3.2.tgz";
+        sha512 = "uoVVA5dchmxZeTMv2Qsd0vhn/RebJYsWo4all1qtrUL3BBhQFn4AQDF4PL+ZvOeK7gczXKEZaSCyMDMwFBlpBg==";
+      };
+    };
+    "commander-2.14.1" = {
+      name = "commander";
+      packageName = "commander";
+      version = "2.14.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz";
+        sha512 = "+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==";
+      };
+    };
+    "commander-2.17.1" = {
+      name = "commander";
+      packageName = "commander";
+      version = "2.17.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz";
+        sha512 = "wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==";
+      };
+    };
+    "commander-2.9.0" = {
+      name = "commander";
+      packageName = "commander";
+      version = "2.9.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz";
+        sha512 = "bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==";
+      };
+    };
+    "component-bind-1.0.0" = {
+      name = "component-bind";
+      packageName = "component-bind";
+      version = "1.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz";
+        sha512 = "WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw==";
+      };
+    };
+    "component-emitter-1.1.2" = {
+      name = "component-emitter";
+      packageName = "component-emitter";
+      version = "1.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz";
+        sha512 = "YhIbp3PJiznERfjlIkK0ue4obZxt2S60+0W8z24ZymOHT8sHloOqWOqZRU2eN5OlY8U08VFsP02letcu26FilA==";
+      };
+    };
+    "component-inherit-0.0.3" = {
+      name = "component-inherit";
+      packageName = "component-inherit";
+      version = "0.0.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz";
+        sha512 = "w+LhYREhatpVqTESyGFg3NlP6Iu0kEKUHETY9GoZP/pQyW4mHFZuFWRUCIqVPZ36ueVLtoOEZaAqbCF2RDndaA==";
+      };
+    };
+    "compressible-1.1.1" = {
+      name = "compressible";
+      packageName = "compressible";
+      version = "1.1.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/compressible/-/compressible-1.1.1.tgz";
+        sha512 = "IwohldOO2F/Oi2ZKOAJE14fVVbYEo5eh3D7+AzmsWovFOHbMAVglHpTYW1N+UExfwiqNfsiY2IBgWkzhc63xgQ==";
+      };
+    };
+    "compression-1.0.11" = {
+      name = "compression";
+      packageName = "compression";
+      version = "1.0.11";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/compression/-/compression-1.0.11.tgz";
+        sha512 = "Xf+wCNAQYsPrvIkWRwGLkkrA2/Kd1TU8VotZZpvkz0+7+5bmxAsYdUahJI3oisroNydtb8NnGy4RMiaeq/GlSg==";
+      };
+    };
+    "concat-stream-2.0.0" = {
+      name = "concat-stream";
+      packageName = "concat-stream";
+      version = "2.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz";
+        sha512 = "MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==";
+      };
+    };
+    "connect-2.25.9" = {
+      name = "connect";
+      packageName = "connect";
+      version = "2.25.9";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/connect/-/connect-2.25.9.tgz";
+        sha512 = "pog2Kti4eIhSbnXj/fvuoLqRoJca1LJO9X3+3sGCAoQSjKM/jY2ER2T925xzN+o0bEGJTt2hR+PzKLXh/E8GNw==";
+      };
+    };
+    "connect-timeout-1.2.2" = {
+      name = "connect-timeout";
+      packageName = "connect-timeout";
+      version = "1.2.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.2.2.tgz";
+        sha512 = "O6Xx6X+JQ/aOrD/OuNKFU8eIMQnupt2pzWAlhxmjpx9Qvni0lS+k/csFgvioaqLF+FcuhRyTbp9nF3huSO2iLw==";
+      };
+    };
+    "cookie-0.1.2" = {
+      name = "cookie";
+      packageName = "cookie";
+      version = "0.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz";
+        sha512 = "+mHmWbhevLwkiBf7QcbZXHr0v4ZQQ/OgHk3fsQHrsMMiGzuvAmU/YMUR+ZfrO/BLAGIWFfx2Z7Oyso0tZR/wiA==";
+      };
+    };
+    "cookie-parser-1.3.2" = {
+      name = "cookie-parser";
+      packageName = "cookie-parser";
+      version = "1.3.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.2.tgz";
+        sha512 = "tz5e2EKahF0l7kgKrFkJkphtY374VIG9qCaPWEJX1dzg6f3O/OFUkgpMoy4Tw/kBK0Fb9WUQpvXBe2RbV+aqXw==";
+      };
+    };
+    "cookie-signature-1.0.4" = {
+      name = "cookie-signature";
+      packageName = "cookie-signature";
+      version = "1.0.4";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.4.tgz";
+        sha512 = "k+lrG38ZC/S7zN6l1/HcF6xF4jMwkIUjnr5afDU7tzFxIfDmKzdqJdXo8HNYaXOuBJ3tPKxSiwCOTA0b3qQfaA==";
+      };
+    };
+    "core-util-is-1.0.3" = {
+      name = "core-util-is";
+      packageName = "core-util-is";
+      version = "1.0.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz";
+        sha512 = "ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==";
+      };
+    };
+    "cors-2.8.5" = {
+      name = "cors";
+      packageName = "cors";
+      version = "2.8.5";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz";
+        sha512 = "KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==";
+      };
+    };
+    "crc-32-1.0.2" = {
+      name = "crc-32";
+      packageName = "crc-32";
+      version = "1.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/crc-32/-/crc-32-1.0.2.tgz";
+        sha512 = "VAF9DaYBjIN1FTholAkIhW75P2c5Sy9AXva/WQ0zo2lVznpCbwAAB5DY+do7mSvXP4br2DPHET9uXST1C6F8IQ==";
+      };
+    };
+    "crc-32-1.2.2" = {
+      name = "crc-32";
+      packageName = "crc-32";
+      version = "1.2.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz";
+        sha512 = "ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==";
+      };
+    };
+    "csrf-2.0.7" = {
+      name = "csrf";
+      packageName = "csrf";
+      version = "2.0.7";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/csrf/-/csrf-2.0.7.tgz";
+        sha512 = "AA22oKr4/2k9QxCLXOS/10NcGudOsxj6oRTa6HjW3spZbJJgKaODdOo1AnZSuz1fSdVNmf4ddXPLsBX+PDeLNA==";
+      };
+    };
+    "cssom-0.2.5" = {
+      name = "cssom";
+      packageName = "cssom";
+      version = "0.2.5";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/cssom/-/cssom-0.2.5.tgz";
+        sha512 = "b9ecqKEfWrNcyzx5+1nmcfi80fPp8dVM8rlAh7fFK14PZbNjp++gRjyZTZfLJQa/Lw0qeCJho7WBIl0nw0v6HA==";
+      };
+    };
+    "csurf-1.4.1" = {
+      name = "csurf";
+      packageName = "csurf";
+      version = "1.4.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/csurf/-/csurf-1.4.1.tgz";
+        sha512 = "uKCR2pZrV0g+FRq0zn06h5fa4qLeBHuVC/WqnvooGjVJSGO3672EJKgGvi/pWqGlBBsVV2U862vG57z90dY/QA==";
+      };
+    };
+    "csv-parse-0.0.6" = {
+      name = "csv-parse";
+      packageName = "csv-parse";
+      version = "0.0.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/csv-parse/-/csv-parse-0.0.6.tgz";
+        sha512 = "ZshgM1uIFJpKWqH8LAC75eHglM91cSXuQG1jAETyd4IZd+ivt3gqlpbXWTjjq81JKP33bA4lXgsi6PJuelcBgQ==";
+      };
+    };
+    "debug-0.6.0" = {
+      name = "debug";
+      packageName = "debug";
+      version = "0.6.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/debug/-/debug-0.6.0.tgz";
+        sha512 = "2vIZf67+gMicLu8McscD1NNhMWbiTSJkhlByoTA1Gw54zOb/9IlxylYG+Kr9z1X2wZTHh1AMSp+YiMjYtLkVUA==";
+      };
+    };
+    "debug-0.7.4" = {
+      name = "debug";
+      packageName = "debug";
+      version = "0.7.4";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz";
+        sha512 = "EohAb3+DSHSGx8carOSKJe8G0ayV5/i609OD0J2orCkuyae7SyZSz2aoLmQF2s0Pj5gITDebwPH7GFBlqOUQ1Q==";
+      };
+    };
+    "debug-1.0.4" = {
+      name = "debug";
+      packageName = "debug";
+      version = "1.0.4";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz";
+        sha512 = "plA8d2GHafT7kXzMDs5r7NSfYP7IKHdO8rZPVAqI33Eum7Vq/Ef/ETXm6NncF/RMif4fzI0RetSArZ6PMIxP0g==";
+      };
+    };
+    "deep-is-0.1.4" = {
+      name = "deep-is";
+      packageName = "deep-is";
+      version = "0.1.4";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz";
+        sha512 = "oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==";
+      };
+    };
+    "depd-0.4.4" = {
+      name = "depd";
+      packageName = "depd";
+      version = "0.4.4";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/depd/-/depd-0.4.4.tgz";
+        sha512 = "NoEUYrSLv7re4u8OtA4yp3ktNC0HaB4dDGPg89TO+suwiVYoBMG8MeSPVpq8RNX9llVyrhknE/pGccsfRMxbhA==";
+      };
+    };
+    "destroy-1.0.3" = {
+      name = "destroy";
+      packageName = "destroy";
+      version = "1.0.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz";
+        sha512 = "KB/AVLKRwZPOEo6/lxkDJ+Bv3jFRRrhmnRMPvpWwmIfUggpzGkQBqolyo8FRf833b/F5rzmy1uVN3fHBkjTxgw==";
+      };
+    };
+    "ee-first-1.0.5" = {
+      name = "ee-first";
+      packageName = "ee-first";
+      version = "1.0.5";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz";
+        sha512 = "+FCut34oNiJD2jD+YL/onRxOHF5ut3xOGgTIyEIOdYfun8AexYhEyurzv9izwhTft1Z7pdy4VlTq51K/sIsQRA==";
+      };
+    };
+    "emitter-http://github.com/component/emitter/archive/1.0.1.tar.gz" = {
+      name = "emitter";
+      packageName = "emitter";
+      version = "1.0.1";
+      src = fetchurl {
+        name = "emitter-1.0.1.tar.gz";
+        url = "https://codeload.github.com/component/emitter/tar.gz/refs/tags/1.0.1";
+        sha256 = "0eae744826723877457f7a7ac7f31d68a5a060673b3a883f6a8e325bf48f313d";
+      };
+    };
+    "engine.io-1.3.1" = {
+      name = "engine.io";
+      packageName = "engine.io";
+      version = "1.3.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/engine.io/-/engine.io-1.3.1.tgz";
+        sha512 = "fjnHWC9SLPoygMp6pqwoxmNkDDdYme4eCRTBTZLmEtGZETCpUEgSwoQjSgyj7IyIjqninKRF+2VeEV2kOniUFQ==";
+      };
+    };
+    "engine.io-client-1.3.1" = {
+      name = "engine.io-client";
+      packageName = "engine.io-client";
+      version = "1.3.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.3.1.tgz";
+        sha512 = "bTOZMqAe7HXhyA/2T7Fve04b/ZZruTHSOqa+yn8U4RFSyRAVPePjopOgJOUNciEfuXo1gx850P5LzaQU28/p3w==";
+      };
+    };
+    "engine.io-parser-1.0.6" = {
+      name = "engine.io-parser";
+      packageName = "engine.io-parser";
+      version = "1.0.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.0.6.tgz";
+        sha512 = "ipbmiNj4OfAL9csof0FlI9L2jkU/lgcUphHjnTDo1KABsA21WtsVy/1OjhCj8xxhNIHtxEZ3/t7uB45gEMhD4g==";
+      };
+    };
+    "errorhandler-1.1.1" = {
+      name = "errorhandler";
+      packageName = "errorhandler";
+      version = "1.1.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/errorhandler/-/errorhandler-1.1.1.tgz";
+        sha512 = "nqVAii3wDkiowAVKDmcuwKOQ/5vsg9GfCcJxSMHgy8yiZUA3mMDpBcHnCVolDYgQ7wsC2yZQVOavR5fGHhFMkg==";
+      };
+    };
+    "escape-html-1.0.1" = {
+      name = "escape-html";
+      packageName = "escape-html";
+      version = "1.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz";
+        sha512 = "z6kAnok8fqVTra7Yu77dZF2Y6ETJlxH58wN38wNyuNQLm8xXdKnfNrlSmfXsTePWP03rRVUKHubtUwanwUi7+g==";
+      };
+    };
+    "exit-on-epipe-1.0.1" = {
+      name = "exit-on-epipe";
+      packageName = "exit-on-epipe";
+      version = "1.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz";
+        sha512 = "h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==";
+      };
+    };
+    "express-3.16.9" = {
+      name = "express";
+      packageName = "express";
+      version = "3.16.9";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/express/-/express-3.16.9.tgz";
+        sha512 = "6Sr9DaXrfOx+z4bY5u0vVQvcv2FQOEw0eKS/3r9x/PDIfQJ8YRVUvKBjrT897NJX3g3XjsqgeZdm2pQNXJL9lw==";
+      };
+    };
+    "express-session-1.7.6" = {
+      name = "express-session";
+      packageName = "express-session";
+      version = "1.7.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/express-session/-/express-session-1.7.6.tgz";
+        sha512 = "cfGbyj0PrZPT/vnqm842HM497fXyvCZYrbL5WzHO689FCO1JSAmDIz6uOsleqpKblpjSQ3ESD5Rww+6s/2WUQg==";
+      };
+    };
+    "fast-levenshtein-2.0.6" = {
+      name = "fast-levenshtein";
+      packageName = "fast-levenshtein";
+      version = "2.0.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz";
+        sha512 = "DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==";
+      };
+    };
+    "finalhandler-0.1.0" = {
+      name = "finalhandler";
+      packageName = "finalhandler";
+      version = "0.1.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/finalhandler/-/finalhandler-0.1.0.tgz";
+        sha512 = "VxIedmyMyIZh8ol/AeWrgVwzDqYVO5wqOcXNuQC0olCvWDgvN7+QyVKHWoZyplbZ82j5p7BynpekYybNSmTjww==";
+      };
+    };
+    "frac-0.3.1" = {
+      name = "frac";
+      packageName = "frac";
+      version = "0.3.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/frac/-/frac-0.3.1.tgz";
+        sha512 = "1Lzf2jOjhIkRaa013KlxNOn2D9FemmQNeYUDpEIyPeFXmpLvbZXJOlaayMBT6JKXx+afQFgQ1QJ4kaF7Z07QFQ==";
+      };
+    };
+    "frac-1.0.6" = {
+      name = "frac";
+      packageName = "frac";
+      version = "1.0.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/frac/-/frac-1.0.6.tgz";
+        sha512 = "RXTHy3vhoqGKWLkk88tlD0n4d+lFyl5Oa1t1DsyHpR7DkXklWnPwnKhdCM+3kDR5fQuxJ3pr6dZ3yuG1YWGdQQ==";
+      };
+    };
+    "frac-1.1.2" = {
+      name = "frac";
+      packageName = "frac";
+      version = "1.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz";
+        sha512 = "w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==";
+      };
+    };
+    "fresh-0.2.2" = {
+      name = "fresh";
+      packageName = "fresh";
+      version = "0.2.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/fresh/-/fresh-0.2.2.tgz";
+        sha512 = "ZGGi8GROK//ijm2gB33sUuN9TjN1tC/dvG4Bt4j6IWrVGpMmudUBCxx+Ir7qePsdREfkpQC4FL8W0jeSOsgv1w==";
+      };
+    };
+    "global-https://github.com/component/global/archive/v2.0.1.tar.gz" = {
+      name = "global";
+      packageName = "global";
+      version = "2.0.1";
+      src = fetchurl {
+        name = "global-2.0.1.tar.gz";
+        url = "https://codeload.github.com/component/global/tar.gz/refs/tags/v2.0.1";
+        sha256 = "42be02b7148745447f6ba21137c972ca82d2cad92d30d63bd4fc310623901785";
+      };
+    };
+    "graceful-readlink-1.0.1" = {
+      name = "graceful-readlink";
+      packageName = "graceful-readlink";
+      version = "1.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz";
+        sha512 = "8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==";
+      };
+    };
+    "harb-0.1.1" = {
+      name = "harb";
+      packageName = "harb";
+      version = "0.1.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/harb/-/harb-0.1.1.tgz";
+        sha512 = "2uzPCmpuC+gfKyvQfeqbH9APr6vYNjxK4q4z+3AL5GHZIeLpXN9tvaD0ZPVdzpSijSO2kwfd5jkSbMO02tIT6g==";
+      };
+    };
+    "has-binary-data-0.1.1" = {
+      name = "has-binary-data";
+      packageName = "has-binary-data";
+      version = "0.1.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/has-binary-data/-/has-binary-data-0.1.1.tgz";
+        sha512 = "XqIrqIgPlA2gxvHKudDsLJt8Xu8B4DvkHyUWGmLWYOAO0rFOL94Ds4NSveSZ1fCjWX22tQgIiRpDKAETex8GCQ==";
+      };
+    };
+    "has-cors-1.0.3" = {
+      name = "has-cors";
+      packageName = "has-cors";
+      version = "1.0.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/has-cors/-/has-cors-1.0.3.tgz";
+        sha512 = "Mxk1ba23PNtB3zPigreijApS3uuH9bhgZkqQtLQj7ydWHsGeb9uOtk4gsK6mZj4rYG6VNS/CT9G1XkYfgItpKg==";
+      };
+    };
+    "iconv-lite-0.4.24" = {
+      name = "iconv-lite";
+      packageName = "iconv-lite";
+      version = "0.4.24";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz";
+        sha512 = "v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==";
+      };
+    };
+    "iconv-lite-0.4.4" = {
+      name = "iconv-lite";
+      packageName = "iconv-lite";
+      version = "0.4.4";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.4.tgz";
+        sha512 = "BnjNp13aZpK4WBGbmjaNHN2MCp3P850n8zd/JLinQJ8Lsnq2Br4o2467C2waMsY5kr7Z41SL1gEqh8Vbfzg15A==";
+      };
+    };
+    "indexof-0.0.1" = {
+      name = "indexof";
+      packageName = "indexof";
+      version = "0.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz";
+        sha512 = "i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg==";
+      };
+    };
+    "inherits-2.0.4" = {
+      name = "inherits";
+      packageName = "inherits";
+      version = "2.0.4";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz";
+        sha512 = "k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==";
+      };
+    };
+    "ipaddr.js-0.1.2" = {
+      name = "ipaddr.js";
+      packageName = "ipaddr.js";
+      version = "0.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-0.1.2.tgz";
+        sha512 = "MGrEjHz4Hk5UVpJXZQ2tHB+bp6xgdRKCAEWdrgFsoAmXCgKAPtj8LqMxgvlWEAj9aN+PpTcvE051uZU3K3kLSQ==";
+      };
+    };
+    "isarray-0.0.1" = {
+      name = "isarray";
+      packageName = "isarray";
+      version = "0.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz";
+        sha512 = "D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==";
+      };
+    };
+    "j-0.4.5" = {
+      name = "j";
+      packageName = "j";
+      version = "0.4.5";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/j/-/j-0.4.5.tgz";
+        sha512 = "4rl55iqQwjRJZlBa6wGKMXoaURSIjE2z7zR8CW7vo9oXZxcBrXqBnpxxhEoFWELQzoc4vZig+E6SLUhrjR9PTg==";
+      };
+    };
+    "json3-3.2.6" = {
+      name = "json3";
+      packageName = "json3";
+      version = "3.2.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/json3/-/json3-3.2.6.tgz";
+        sha512 = "KA+GHhYTLTo7Ri4DyjwUgW8kn98AYtVZtBC94qL5yD0ZSYct8/eF8qBmTNyk+gPE578bKeIL4WBq+MUyd1I26g==";
+      };
+    };
+    "keypress-0.1.0" = {
+      name = "keypress";
+      packageName = "keypress";
+      version = "0.1.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz";
+        sha512 = "x0yf9PL/nx9Nw9oLL8ZVErFAk85/lslwEP7Vz7s5SI1ODXZIgit3C5qyWjw4DxOuO/3Hb4866SQh28a1V1d+WA==";
+      };
+    };
+    "levn-0.3.0" = {
+      name = "levn";
+      packageName = "levn";
+      version = "0.3.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz";
+        sha512 = "0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==";
+      };
+    };
+    "livescript-1.5.0" = {
+      name = "livescript";
+      packageName = "livescript";
+      version = "1.5.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/livescript/-/livescript-1.5.0.tgz";
+        sha512 = "ng8B3l2Ovk71QD7n9B8Oc4kskPL4gnQLOXEPpyqUXI0lcN/FiDO9e9LnoxrIyvHPuNPj71qlFO9mvSfft3byJg==";
+      };
+    };
+    "media-typer-0.2.0" = {
+      name = "media-typer";
+      packageName = "media-typer";
+      version = "0.2.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/media-typer/-/media-typer-0.2.0.tgz";
+        sha512 = "TSggxYk75oP4tae7JkT8InpcFGUP4340zg1dOWjcu9qcphaDKtXEuNUv3OD4vJ+gVTvIDK797W0uYeNm8qqsDg==";
+      };
+    };
+    "merge-descriptors-0.0.2" = {
+      name = "merge-descriptors";
+      packageName = "merge-descriptors";
+      version = "0.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz";
+        sha512 = "dYBT4Ep+t/qnPeJcnMymmhTdd4g8/hn48ciaDqLAkfRf8abzLPS6Rb6EBdz5CZCL8tzZuI5ps9MhGQGxk+EuKg==";
+      };
+    };
+    "method-override-2.1.3" = {
+      name = "method-override";
+      packageName = "method-override";
+      version = "2.1.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/method-override/-/method-override-2.1.3.tgz";
+        sha512 = "SmXDApXkRCv9xh+TxEJMs2aNMcygKazQC7M93S7Yxd2t4XSPHRnrxfGzLfzGArqrY0s5CPPAIPQRoBTUqk+G0g==";
+      };
+    };
+    "methods-1.1.0" = {
+      name = "methods";
+      packageName = "methods";
+      version = "1.1.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/methods/-/methods-1.1.0.tgz";
+        sha512 = "Th88HxNePtsAmz0WjEhVVyRGv9AQFLv4z6zOj4Dt15PjsKLWB8JXSmxzP+Q27139+AXao0AlCWvonFuJhu4GuA==";
+      };
+    };
+    "mime-1.2.11" = {
+      name = "mime";
+      packageName = "mime";
+      version = "1.2.11";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz";
+        sha512 = "Ysa2F/nqTNGHhhm9MV8ure4+Hc+Y8AWiqUdHxsO7xu8zc92ND9f3kpALHjaP026Ft17UfxrMt95c50PLUeynBw==";
+      };
+    };
+    "mime-types-1.0.2" = {
+      name = "mime-types";
+      packageName = "mime-types";
+      version = "1.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz";
+        sha512 = "echfutj/t5SoTL4WZpqjA1DCud1XO0WQF3/GJ48YBmc4ZMhCK77QA6Z/w6VTQERLKuJ4drze3kw2TUT8xZXVNw==";
+      };
+    };
+    "minimatch-9.0.0" = {
+      name = "minimatch";
+      packageName = "minimatch";
+      version = "9.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz";
+        sha512 = "0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==";
+      };
+    };
+    "minimist-0.0.10" = {
+      name = "minimist";
+      packageName = "minimist";
+      version = "0.0.10";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz";
+        sha512 = "iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==";
+      };
+    };
+    "minimist-0.0.8" = {
+      name = "minimist";
+      packageName = "minimist";
+      version = "0.0.8";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz";
+        sha512 = "miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==";
+      };
+    };
+    "mkdirp-0.3.5" = {
+      name = "mkdirp";
+      packageName = "mkdirp";
+      version = "0.3.5";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz";
+        sha512 = "8OCq0De/h9ZxseqzCH8Kw/Filf5pF/vMI6+BH7Lu0jXz2pqYCjTAQRolSxRIi+Ax+oCCjlxoJMP0YQ4XlrQNHg==";
+      };
+    };
+    "mkdirp-0.5.0" = {
+      name = "mkdirp";
+      packageName = "mkdirp";
+      version = "0.5.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz";
+        sha512 = "xjjNGy+ry1lhtIKcr2PT6ok3aszhQfgrUDp4OZLHacgRgFmF6XR9XCOJVcXlVGQonIqXcK1DvqgKKQOPWYGSfw==";
+      };
+    };
+    "morgan-1.2.3" = {
+      name = "morgan";
+      packageName = "morgan";
+      version = "1.2.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/morgan/-/morgan-1.2.3.tgz";
+        sha512 = "epRQVQDr/otLiBetuLFEwQWHXiuIahy9ezUzpVDYzO8OtgzqDty8VCpd8hs7HGnrRk0LXlFdi9zDmMjajmWwvw==";
+      };
+    };
+    "ms-0.6.2" = {
+      name = "ms";
+      packageName = "ms";
+      version = "0.6.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz";
+        sha512 = "/pc3eh7TWorTtbvXg8je4GvrvEqCfH7PA3P7iW01yL2E53FKixzgMBaQi0NOPbMJqY34cBSvR0tZtmlTkdUG4A==";
+      };
+    };
+    "multiparty-3.3.2" = {
+      name = "multiparty";
+      packageName = "multiparty";
+      version = "3.3.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz";
+        sha512 = "FX6dDOKzDpkrb5/+Imq+V6dmCZNnC02tMDiZfrgHSYgfQj6CVPGzOVqfbHKt/Vy4ZZsmMPXkulyLf92lCyvV7A==";
+      };
+    };
+    "mz-1.3.0" = {
+      name = "mz";
+      packageName = "mz";
+      version = "1.3.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/mz/-/mz-1.3.0.tgz";
+        sha512 = "x+R7YSsEySSpV5uEB+C47JTmxv+YKKNsW3W+hjvq8NbLn8ntLgYXGrR5RjQ3Fs0e7Chw8Rp/1e5eo0n5LP76cw==";
+      };
+    };
+    "nan-0.3.2" = {
+      name = "nan";
+      packageName = "nan";
+      version = "0.3.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/nan/-/nan-0.3.2.tgz";
+        sha512 = "V9/Pyy5Oelv6vVJP9X+dAzU3IO19j6YXrJnODHxP2h54hTvfFQGahdsQV6Ule/UukiEJk1SkQ/aUyWUm61RBQw==";
+      };
+    };
+    "native-or-bluebird-1.1.2" = {
+      name = "native-or-bluebird";
+      packageName = "native-or-bluebird";
+      version = "1.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.1.2.tgz";
+        sha512 = "Bgn5FHNkd+lPTjIzq1NVU/VZTvPKFvhdIDEyYjxrKNrScSXbVvNVzOKwoleysun0/HoN7R+TXmK9mCtEs84osA==";
+      };
+    };
+    "negotiator-0.4.7" = {
+      name = "negotiator";
+      packageName = "negotiator";
+      version = "0.4.7";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/negotiator/-/negotiator-0.4.7.tgz";
+        sha512 = "ujxWwyRfZ6udAgHGECQC3JDO9e6UAsuItfUMcqA0Xf2OLNQTveFVFx+fHGIJ5p0MJaJrZyGQqPwzuN0NxJzEKA==";
+      };
+    };
+    "node-uuid-1.4.1" = {
+      name = "node-uuid";
+      packageName = "node-uuid";
+      version = "1.4.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz";
+        sha512 = "yli1av4CgutKcqitN8ILW9lMxOrsGJFrhy5jlwcY5GLYxC3dsMyvmKJOf2Zy55CK2e99gQfVnht67b6tmAdiDQ==";
+      };
+    };
+    "object-assign-4.1.1" = {
+      name = "object-assign";
+      packageName = "object-assign";
+      version = "4.1.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz";
+        sha512 = "rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==";
+      };
+    };
+    "object-component-0.0.3" = {
+      name = "object-component";
+      packageName = "object-component";
+      version = "0.0.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz";
+        sha512 = "S0sN3agnVh2SZNEIGc0N1X4Z5K0JeFbGBrnuZpsxuUh5XLF0BnvWkMjRXo/zGKLd/eghvNIKcx1pQkmUjXIyrA==";
+      };
+    };
+    "on-finished-2.1.0" = {
+      name = "on-finished";
+      packageName = "on-finished";
+      version = "2.1.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz";
+        sha512 = "33+g6TZkplndl+2k2VNO1YphX5hm79DGhBP6TJcDI9o1sCFbUvO2bgxPdGanIFqZK4su6OVLwPHY9GkLQrojgA==";
+      };
+    };
+    "on-headers-1.0.2" = {
+      name = "on-headers";
+      packageName = "on-headers";
+      version = "1.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz";
+        sha512 = "pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==";
+      };
+    };
+    "optimist-0.3.7" = {
+      name = "optimist";
+      packageName = "optimist";
+      version = "0.3.7";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz";
+        sha512 = "TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==";
+      };
+    };
+    "optimist-0.6.1" = {
+      name = "optimist";
+      packageName = "optimist";
+      version = "0.6.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz";
+        sha512 = "snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==";
+      };
+    };
+    "optionator-0.8.3" = {
+      name = "optionator";
+      packageName = "optionator";
+      version = "0.8.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz";
+        sha512 = "+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==";
+      };
+    };
+    "options-0.0.6" = {
+      name = "options";
+      packageName = "options";
+      version = "0.0.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/options/-/options-0.0.6.tgz";
+        sha512 = "bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg==";
+      };
+    };
+    "optparse-1.0.3" = {
+      name = "optparse";
+      packageName = "optparse";
+      version = "1.0.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/optparse/-/optparse-1.0.3.tgz";
+        sha512 = "dGvcQl7PJah19cfi6jBcTZrZ4XorYp7VPu1qnoeP1TsKNwdRtG5HRdlTb4PWFPbHRo2fXhyQtuW/SF1WVY1HPQ==";
+      };
+    };
+    "parsejson-0.0.1" = {
+      name = "parsejson";
+      packageName = "parsejson";
+      version = "0.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/parsejson/-/parsejson-0.0.1.tgz";
+        sha512 = "W9CRvTfYQY/kbRc5Q6YTWarb/QDxdEGbd6RCP8CLUQDJV89RVHoS2A0dZYNtAcq31fulGNN4ZhAhiQQazwlKJg==";
+      };
+    };
+    "parseqs-0.0.2" = {
+      name = "parseqs";
+      packageName = "parseqs";
+      version = "0.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/parseqs/-/parseqs-0.0.2.tgz";
+        sha512 = "vyyyfQGUFZnDhgrrdn+hh1JuOfvbXU5oRr6dijfkSIbaFuxGgTSCA/RNVcsADmo0k2NX6wERVTMKkXokjuObJA==";
+      };
+    };
+    "parseuri-0.0.2" = {
+      name = "parseuri";
+      packageName = "parseuri";
+      version = "0.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/parseuri/-/parseuri-0.0.2.tgz";
+        sha512 = "m0H+R0u5LXOx8sbxufnvgKrRLpkVpvtMf0AyWXYSqLwo2MWrVEgCIbgpaSVa398xl6wTLe0A7CGhiC4hBdEzHQ==";
+      };
+    };
+    "parseurl-1.3.3" = {
+      name = "parseurl";
+      packageName = "parseurl";
+      version = "1.3.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz";
+        sha512 = "CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==";
+      };
+    };
+    "pause-0.0.1" = {
+      name = "pause";
+      packageName = "pause";
+      version = "0.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz";
+        sha512 = "KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==";
+      };
+    };
+    "prelude-ls-1.1.2" = {
+      name = "prelude-ls";
+      packageName = "prelude-ls";
+      version = "1.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz";
+        sha512 = "ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==";
+      };
+    };
+    "printj-1.1.2" = {
+      name = "printj";
+      packageName = "printj";
+      version = "1.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz";
+        sha512 = "zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==";
+      };
+    };
+    "proxy-addr-1.0.1" = {
+      name = "proxy-addr";
+      packageName = "proxy-addr";
+      version = "1.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.1.tgz";
+        sha512 = "rIUGzBlSfkJMWWCgsd4N5wvVSNAcJZg//UwPZumDIbScHRUzuSOjBmIdyICiKkB9yArv+er9qC6RA/NL3AWc6A==";
+      };
+    };
+    "qs-2.2.2" = {
+      name = "qs";
+      packageName = "qs";
+      version = "2.2.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/qs/-/qs-2.2.2.tgz";
+        sha512 = "i0PpYJWWhn7DevbolgusRac1ijaEG/jrigNv+WHbTKYWtTqAc/D+6qwAdZ24kZ4ZH3V5hKiqy15ldAplk4V0TQ==";
+      };
+    };
+    "range-parser-1.0.0" = {
+      name = "range-parser";
+      packageName = "range-parser";
+      version = "1.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/range-parser/-/range-parser-1.0.0.tgz";
+        sha512 = "wOH5LIH2ZHo0P7/bwkR+aNbJ+kv3CHVX4B8qs9GqbtY29fi1bGPV5xczrutN20G+Z4XhRqRMTW3q0S4iyJJPfw==";
+      };
+    };
+    "raw-body-1.3.0" = {
+      name = "raw-body";
+      packageName = "raw-body";
+      version = "1.3.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/raw-body/-/raw-body-1.3.0.tgz";
+        sha512 = "iuI1bOSi9tEmVCrXq02ZysXatTrhAu+fSo7XOQHhMo4g87dSy9YB2W/9Udwhz0bPpFk4UcoLhjrHgpPbRD3ktA==";
+      };
+    };
+    "readable-stream-1.1.14" = {
+      name = "readable-stream";
+      packageName = "readable-stream";
+      version = "1.1.14";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz";
+        sha512 = "+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==";
+      };
+    };
+    "readable-stream-3.6.2" = {
+      name = "readable-stream";
+      packageName = "readable-stream";
+      version = "3.6.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz";
+        sha512 = "9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==";
+      };
+    };
+    "redis-0.12.1" = {
+      name = "redis";
+      packageName = "redis";
+      version = "0.12.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz";
+        sha512 = "DtqxdmgmVAO7aEyxaXBiUTvhQPOYznTIvmPzs9AwWZqZywM50JlFxQjFhicI+LVbaun7uwfO3izuvc1L8NlPKQ==";
+      };
+    };
+    "response-time-2.0.1" = {
+      name = "response-time";
+      packageName = "response-time";
+      version = "2.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/response-time/-/response-time-2.0.1.tgz";
+        sha512 = "5C+Fn78qkdeI3GLK8xRaHLp7CJvH1d7Z+5ZX9nO1azJnF4CPR/Gid3EJY9s8hyta+ssJGETO6BD11V1taXriiw==";
+      };
+    };
+    "rndm-1.1.1" = {
+      name = "rndm";
+      packageName = "rndm";
+      version = "1.1.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/rndm/-/rndm-1.1.1.tgz";
+        sha512 = "0hmr77ro4CsIi6ywLsZ+QqUrwll5DHFdmgeKtf9cBBhiW47BHL7VG6bzhdepnwH4gL3gREnLuP2gCiPRnep5cw==";
+      };
+    };
+    "safe-buffer-5.2.1" = {
+      name = "safe-buffer";
+      packageName = "safe-buffer";
+      version = "5.2.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz";
+        sha512 = "rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==";
+      };
+    };
+    "safer-buffer-2.1.2" = {
+      name = "safer-buffer";
+      packageName = "safer-buffer";
+      version = "2.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz";
+        sha512 = "YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==";
+      };
+    };
+    "scmp-1.0.0" = {
+      name = "scmp";
+      packageName = "scmp";
+      version = "1.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/scmp/-/scmp-1.0.0.tgz";
+        sha512 = "gCzsBFLpXrXnq60hYFV4hc4b5a3nIWTKtFWMYvlcXqs5gHKTR445CO3QbFRZW/O+9tRIVTeC46/MXbq1Se/1Sw==";
+      };
+    };
+    "send-0.8.3" = {
+      name = "send";
+      packageName = "send";
+      version = "0.8.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/send/-/send-0.8.3.tgz";
+        sha512 = "pB//2WPgYGXQPNUq1XJ2wLdZU4P4fchsM09vfDdeEYOxs+4OnQKN+DqJJQ0kAxP5mpdLJf3nWcLftKn2Pb+mvg==";
+      };
+    };
+    "send-0.8.5" = {
+      name = "send";
+      packageName = "send";
+      version = "0.8.5";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/send/-/send-0.8.5.tgz";
+        sha512 = "U6FiwCZ1ZCtLqLj2vgEX+3CljIDAzrkCSsbwdS+VKWxYR9/5Rk7GR+Rg79np/CsvElh8u7q3YmJu6PLGdDJqgw==";
+      };
+    };
+    "serve-favicon-2.0.1" = {
+      name = "serve-favicon";
+      packageName = "serve-favicon";
+      version = "2.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.0.1.tgz";
+        sha512 = "ER7Nk+que+Og6kDJpADjLMkTkllBKWz9FPef5A+uELiYAODTjaMJMszKhzUzsNcvqXM5+mzAdpv/6FaxRlJUng==";
+      };
+    };
+    "serve-index-1.1.6" = {
+      name = "serve-index";
+      packageName = "serve-index";
+      version = "1.1.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/serve-index/-/serve-index-1.1.6.tgz";
+        sha512 = "uWGuAekfhMHBaKk2ZoGZn9b5GLpdUH5lHMo2Dkkiakg6eHNQBH8CR/x2RVVwh7FPPzA7L8ppz8WyjXNYurVMsQ==";
+      };
+    };
+    "serve-static-1.5.4" = {
+      name = "serve-static";
+      packageName = "serve-static";
+      version = "1.5.4";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/serve-static/-/serve-static-1.5.4.tgz";
+        sha512 = "6dxbEeZO39/rL80vlKRi6OatwVN+f2cAou95AVKOQbMKuZ9ln2rDMjjRQN6tu7u9daaaDsU1+hL4NW7zrSMzZA==";
+      };
+    };
+    "socialcalc-2.3.0" = {
+      name = "socialcalc";
+      packageName = "socialcalc";
+      version = "2.3.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/socialcalc/-/socialcalc-2.3.0.tgz";
+        sha512 = "hkK5c7eRRGzOiRNPFCQ/kzv2wqOSFaD4AtYag962r0jV0mlyhTQ7xvs3r14MB3Xbo2hAWq5AKYddrtqvuWvDAA==";
+      };
+    };
+    "socket.io-1.0.6" = {
+      name = "socket.io";
+      packageName = "socket.io";
+      version = "1.0.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/socket.io/-/socket.io-1.0.6.tgz";
+        sha512 = "1x7TkMh8aKfLoXuXe5rXnDnv3xfcOFrDM6hR9z15dpZ83tTxt2NUxnpuGL2zMIAJQ4DitKiadEBvBVju5cxcHw==";
+      };
+    };
+    "socket.io-adapter-0.2.0" = {
+      name = "socket.io-adapter";
+      packageName = "socket.io-adapter";
+      version = "0.2.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.2.0.tgz";
+        sha512 = "3PlX+MOlpHiY+ZTbKhpE4i+M4u8hFUlVyqFP4K/mH+t+D9bMKATFqUUY3zWQMEo2g/1ckosURXviQw6M8R/y8A==";
+      };
+    };
+    "socket.io-client-1.0.6" = {
+      name = "socket.io-client";
+      packageName = "socket.io-client";
+      version = "1.0.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.0.6.tgz";
+        sha512 = "itdtz6fQBTFIDBP4+hJox0OlT+SbCVdENjPgjMup3ehu7OsiG6t0FYBXCx+k/upt9lbeyp9BmUNNi5EfnGa5Vw==";
+      };
+    };
+    "socket.io-parser-2.1.2" = {
+      name = "socket.io-parser";
+      packageName = "socket.io-parser";
+      version = "2.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.1.2.tgz";
+        sha512 = "eVkt8prgw20H+4P8Iw6tis/w7leiN5EW/93Vq+KL8w+yNJu+QNgaej2Cgt8FhVCVuN3AHyLU50vXvM8cpUR1JQ==";
+      };
+    };
+    "socket.io-parser-2.2.0" = {
+      name = "socket.io-parser";
+      packageName = "socket.io-parser";
+      version = "2.2.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.0.tgz";
+        sha512 = "uW3UiLVibAyleKq8r/yZe1oPO51olhY18T6HtnN0iI6RLqJfYC0YiyAFlsPw1+8I0Z1qFd8jFLTRZo2vr6ISxA==";
+      };
+    };
+    "source-map-0.1.34" = {
+      name = "source-map";
+      packageName = "source-map";
+      version = "0.1.34";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz";
+        sha512 = "yfCwDj0vR9RTwt3pEzglgb3ZgmcXHt6DjG3bjJvzPwTL+5zDQ2MhmSzAcTy0GTiQuCiriSWXvWM1/NhKdXuoQA==";
+      };
+    };
+    "source-map-0.5.7" = {
+      name = "source-map";
+      packageName = "source-map";
+      version = "0.5.7";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz";
+        sha512 = "LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==";
+      };
+    };
+    "ssf-0.10.3" = {
+      name = "ssf";
+      packageName = "ssf";
+      version = "0.10.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/ssf/-/ssf-0.10.3.tgz";
+        sha512 = "pRuUdW0WwyB2doSqqjWyzwCD6PkfxpHAHdZp39K3dp/Hq7f+xfMwNAWIi16DyrRg4gg9c/RvLYkJTSawTPTm1w==";
+      };
+    };
+    "ssf-0.8.2" = {
+      name = "ssf";
+      packageName = "ssf";
+      version = "0.8.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/ssf/-/ssf-0.8.2.tgz";
+        sha512 = "+ZkFDAG+ImJ48DcZvabx6YTrZ67DKkM0kbyOOtH73mbUEvNhQWWgRZrHC8+k7GuGKWQnACYLi7bj0eCt1jmosQ==";
+      };
+    };
+    "ssf-0.9.4" = {
+      name = "ssf";
+      packageName = "ssf";
+      version = "0.9.4";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/ssf/-/ssf-0.9.4.tgz";
+        sha512 = "PGlTb3r+W8MneGKfN5B+5TFcaA4HUQcpYrVvTW+gMiM5dsqv1Y5h47OQu0okhVLzuQSRoZQbrP7g6zEcP+UrTg==";
+      };
+    };
+    "stream-counter-0.2.0" = {
+      name = "stream-counter";
+      packageName = "stream-counter";
+      version = "0.2.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz";
+        sha512 = "GjA2zKc2iXUUKRcOxXQmhEx0Ev3XHJ6c8yWGqhQjWwhGrqNwSsvq9YlRLgoGtZ5Kx2Ln94IedaqJ5GUG6aBbxA==";
+      };
+    };
+    "string_decoder-0.10.31" = {
+      name = "string_decoder";
+      packageName = "string_decoder";
+      version = "0.10.31";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz";
+        sha512 = "ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==";
+      };
+    };
+    "string_decoder-1.3.0" = {
+      name = "string_decoder";
+      packageName = "string_decoder";
+      version = "1.3.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz";
+        sha512 = "hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==";
+      };
+    };
+    "stylus-0.27.2" = {
+      name = "stylus";
+      packageName = "stylus";
+      version = "0.27.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/stylus/-/stylus-0.27.2.tgz";
+        sha512 = "A09OMYaAcFsJK/Vk7ZBd6oVAQT3cckz5ErTBxhJinbkkJ0MFO788cgjwznA8tGKhAP6yswJci8+adWTalaJisw==";
+      };
+    };
+    "thenify-3.3.1" = {
+      name = "thenify";
+      packageName = "thenify";
+      version = "3.3.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz";
+        sha512 = "RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==";
+      };
+    };
+    "thenify-all-1.6.0" = {
+      name = "thenify-all";
+      packageName = "thenify-all";
+      version = "1.6.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz";
+        sha512 = "RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==";
+      };
+    };
+    "tinycolor-0.0.1" = {
+      name = "tinycolor";
+      packageName = "tinycolor";
+      version = "0.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/tinycolor/-/tinycolor-0.0.1.tgz";
+        sha512 = "+CorETse1kl98xg0WAzii8DTT4ABF4R3nquhrkIbVGcw1T8JYs5Gfx9xEfGINPUZGDj9C4BmOtuKeaTtuuRolg==";
+      };
+    };
+    "to-array-0.1.3" = {
+      name = "to-array";
+      packageName = "to-array";
+      version = "0.1.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/to-array/-/to-array-0.1.3.tgz";
+        sha512 = "JQk/QMS4oHyU2VufVeyjN25dcnZnr1PV1pa1oKSj7l5tVO9WrU62og3fYzB3mrgJZZgBxdrrA/v6iZzMDuyFYw==";
+      };
+    };
+    "type-check-0.3.2" = {
+      name = "type-check";
+      packageName = "type-check";
+      version = "0.3.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz";
+        sha512 = "ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==";
+      };
+    };
+    "type-is-1.3.2" = {
+      name = "type-is";
+      packageName = "type-is";
+      version = "1.3.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/type-is/-/type-is-1.3.2.tgz";
+        sha512 = "sdIhnvhWEyIP2DKjj1o9tL31m8vFxDfLPD56KXz2absqY5AF2QYkJC7Wrw2fkzsZA9mv+PCtgyB7EqYOgR+r3Q==";
+      };
+    };
+    "typedarray-0.0.6" = {
+      name = "typedarray";
+      packageName = "typedarray";
+      version = "0.0.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz";
+        sha512 = "/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==";
+      };
+    };
+    "uglify-js-1.2.6" = {
+      name = "uglify-js";
+      packageName = "uglify-js";
+      version = "1.2.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/uglify-js/-/uglify-js-1.2.6.tgz";
+        sha512 = "bMAZaFjLe07fmPbfUPoXzyZaB60kpC5EP63Xcqf9/Kt00fgNtQ3q+wAJt9aJh1iimi9vKkyIYgvXghdHb//IEg==";
+      };
+    };
+    "uglify-js-2.4.15" = {
+      name = "uglify-js";
+      packageName = "uglify-js";
+      version = "2.4.15";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.15.tgz";
+        sha512 = "ZK10n0Y1qoR3Q5JJtVjm3ebSZEV2VCDA6g+BZyolGROIMCjtYzt+UtfrPMaX3inwcmewCbkdX78tozF5mrJ8ZA==";
+      };
+    };
+    "uglify-to-browserify-1.0.2" = {
+      name = "uglify-to-browserify";
+      packageName = "uglify-to-browserify";
+      version = "1.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz";
+        sha512 = "vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==";
+      };
+    };
+    "uid-safe-1.0.1" = {
+      name = "uid-safe";
+      packageName = "uid-safe";
+      version = "1.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/uid-safe/-/uid-safe-1.0.1.tgz";
+        sha512 = "+gRoyiC2ZLfhUZDL5VrKFCWNirAe/MTTiVhhZ3S0QGw35KqOFbagZcUSzZOgXR3aazpN/zAYJcaQ54sFlU5tkA==";
+      };
+    };
+    "uid-safe-1.1.0" = {
+      name = "uid-safe";
+      packageName = "uid-safe";
+      version = "1.1.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/uid-safe/-/uid-safe-1.1.0.tgz";
+        sha512 = "7+QtWs9zioL/iQX61G+4h3EPyr3H+tINIp0IAV4EL32vdf7qmFyuW0BgRqWl7p5oZOsEQrlL0bY7m5D8tp7b1w==";
+      };
+    };
+    "underscore-1.13.6" = {
+      name = "underscore";
+      packageName = "underscore";
+      version = "1.13.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz";
+        sha512 = "+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==";
+      };
+    };
+    "utf8-2.0.0" = {
+      name = "utf8";
+      packageName = "utf8";
+      version = "2.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz";
+        sha512 = "jWXHr+bQ8RsWazLzVY3V7XACPTbBHYSg/VoDVok+DBQk5ULm0AuBCNb9tGmjq2H+znnkBFwjhzzCbn9G3xlYcA==";
+      };
+    };
+    "util-deprecate-1.0.2" = {
+      name = "util-deprecate";
+      packageName = "util-deprecate";
+      version = "1.0.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz";
+        sha512 = "EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==";
+      };
+    };
+    "utils-merge-1.0.0" = {
+      name = "utils-merge";
+      packageName = "utils-merge";
+      version = "1.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz";
+        sha512 = "HwU9SLQEtyo+0uoKXd1nkLqigUWLB+QuNQR4OcmB73eWqksM5ovuqcycks2x043W8XVb75rG1HQ0h93TMXkzQQ==";
+      };
+    };
+    "uuid-pure-1.0.10" = {
+      name = "uuid-pure";
+      packageName = "uuid-pure";
+      version = "1.0.10";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/uuid-pure/-/uuid-pure-1.0.10.tgz";
+        sha512 = "kTOPlO7kzgyMAr3mjS33V/4Mopdr7VPaob5mAWaeSaa0dtHTubIGvaP2zgWmJvyGZ5JPwevHDgTRoFNrQh7Q7g==";
+      };
+    };
+    "vary-0.1.0" = {
+      name = "vary";
+      packageName = "vary";
+      version = "0.1.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/vary/-/vary-0.1.0.tgz";
+        sha512 = "tyyeG46NQdwyVP/RsWLSrT78ouwEuvwk9gK8vQK4jdXmqoXtTXW+vsCfNcnqRhigF8olV34QVZarmAi6wBV2Mw==";
+      };
+    };
+    "vary-1.0.1" = {
+      name = "vary";
+      packageName = "vary";
+      version = "1.0.1";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz";
+        sha512 = "yNsH+tC0r8quK2tg/yqkXqqaYzeKTkSqQ+8T6xCoWgOi/bU/omMYz+6k+I91JJJDeltJzI7oridTOq6OYkY0Tw==";
+      };
+    };
+    "vary-1.1.2" = {
+      name = "vary";
+      packageName = "vary";
+      version = "1.1.2";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz";
+        sha512 = "BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==";
+      };
+    };
+    "vhost-2.0.0" = {
+      name = "vhost";
+      packageName = "vhost";
+      version = "2.0.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/vhost/-/vhost-2.0.0.tgz";
+        sha512 = "TSExWM12MVtvIuBLMPyBuWBQLbHnmDZ3zfsoZwcUmKxzPX8l/cHKl5vVfbo8/KZ56UBAc/tTYXbaDGVDaIcrWw==";
+      };
+    };
+    "voc-1.2.0" = {
+      name = "voc";
+      packageName = "voc";
+      version = "1.2.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/voc/-/voc-1.2.0.tgz";
+        sha512 = "BOuDjFFYvJdZO6e/N65AlaDItXo2TgyLjeyRYcqgAPkXpp5yTJcvkL2n+syO1r9Qc5g96tfBD2tuiMhYDmaGcA==";
+      };
+    };
+    "word-wrap-1.2.3" = {
+      name = "word-wrap";
+      packageName = "word-wrap";
+      version = "1.2.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz";
+        sha512 = "Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==";
+      };
+    };
+    "wordwrap-0.0.3" = {
+      name = "wordwrap";
+      packageName = "wordwrap";
+      version = "0.0.3";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz";
+        sha512 = "1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==";
+      };
+    };
+    "ws-0.4.31" = {
+      name = "ws";
+      packageName = "ws";
+      version = "0.4.31";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/ws/-/ws-0.4.31.tgz";
+        sha512 = "mWiVQ9qZGPXvLxQ4xGy58Ix5Bw0L99SB+hDT8L59bty4fbnQczaGl4YEWR7AzLQGbvPn/30r9/o41dPiSuUmYw==";
+      };
+    };
+    "xlsjs-0.7.6" = {
+      name = "xlsjs";
+      packageName = "xlsjs";
+      version = "0.7.6";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/xlsjs/-/xlsjs-0.7.6.tgz";
+        sha512 = "IQtL2z+BVYaIVzEhknZ1YBr8ItUbqiS7kaQZ3O35/k1q+kSgjVxmzwno6r3EbBgEWhrVCad2mKbnFeMmEE5zdw==";
+      };
+    };
+    "xlsx-0.14.5" = {
+      name = "xlsx";
+      packageName = "xlsx";
+      version = "0.14.5";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/xlsx/-/xlsx-0.14.5.tgz";
+        sha512 = "s/5f4/mjeWREmIWZ+HtDfh/rnz51ar+dZ4LWKZU3u9VBx2zLdSIWTdXgoa52/pnZ9Oe/Vu1W1qzcKzLVe+lq4w==";
+      };
+    };
+    "xlsx-0.9.13" = {
+      name = "xlsx";
+      packageName = "xlsx";
+      version = "0.9.13";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/xlsx/-/xlsx-0.9.13.tgz";
+        sha512 = "C3SsHOLbx05UCN4iRW6iL/JdO1XyPzv7XzNmLInfo2jVfZAL2XoJx3fj5q8fIZZaHI7/7uYqToQzHmHIyWTOJw==";
+      };
+    };
+    "xmlhttprequest-https://github.com/LearnBoost/node-XMLHttpRequest/archive/0f36d0b5ebc03d85f860d42a64ae9791e1daa433.tar.gz" = {
+      name = "xmlhttprequest";
+      packageName = "xmlhttprequest";
+      version = "1.5.0";
+      src = fetchurl {
+        name = "xmlhttprequest-1.5.0.tar.gz";
+        url = "https://codeload.github.com/LearnBoost/node-XMLHttpRequest/tar.gz/0f36d0b5ebc03d85f860d42a64ae9791e1daa433";
+        sha256 = "28dd0394d85befe8be4e9cd9f6803102780c62cbb09298cb174b52ff9777624f";
+      };
+    };
+    "xoauth2-1.2.0" = {
+      name = "xoauth2";
+      packageName = "xoauth2";
+      version = "1.2.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/xoauth2/-/xoauth2-1.2.0.tgz";
+        sha512 = "hKuNbkj3q/ifCcfWnW6KURP+6ExSuLdLG007gasNhMEMKlLaejNkIA6eu5Ol1xPP0/kzTuA87XHDaAcUw5k73Q==";
+      };
+    };
+    "zappajs-0.5.0" = {
+      name = "zappajs";
+      packageName = "zappajs";
+      version = "0.5.0";
+      src = fetchurl {
+        url = "https://registry.npmjs.org/zappajs/-/zappajs-0.5.0.tgz";
+        sha512 = "db+NKrYY4f3EPGuIqG5dnZ1Y9a4bl7Mg0JgDaniHS7Vb7KM+37cEybXKnGrwMBvHdFl2xFvrHwQ2QbEqrddBMg==";
+      };
+    };
+  };
+in
+{
+  "whitebophir-git+https://github.com/audreyt/ethercalc.git#b196277081d677be991d104e454a52d242ef0189" = nodeEnv.buildNodePackage {
+    name = "ethercalc";
+    packageName = "ethercalc";
+    version = "0.20201228.1";
+    src = fetchgit {
+      url = "https://github.com/audreyt/ethercalc.git";
+      rev = "b196277081d677be991d104e454a52d242ef0189";
+      sha256 = "4494bada571057d86009f27470cc34f1e8a3b2c03b395cdba639c08d502a9bfe";
+    };
+    dependencies = [
+      sources."accepts-1.0.7"
+      sources."adler-32-1.2.0"
+      sources."after-0.8.1"
+      sources."amdefine-1.0.1"
+      sources."any-promise-1.3.0"
+      sources."arraybuffer.slice-0.0.6"
+      sources."async-0.2.10"
+      sources."babyparse-0.2.1"
+      sources."balanced-match-1.0.2"
+      sources."base64-arraybuffer-0.1.2"
+      sources."base64-url-1.2.1"
+      sources."base64id-0.1.0"
+      sources."basic-auth-1.0.0"
+      sources."basic-auth-connect-1.0.0"
+      sources."batch-0.5.1"
+      sources."better-assert-1.0.2"
+      sources."blob-0.0.2"
+      (sources."body-parser-1.6.7" // {
+        dependencies = [
+          sources."iconv-lite-0.4.4"
+        ];
+      })
+      sources."brace-expansion-2.0.1"
+      sources."buffer-crc32-0.2.3"
+      sources."buffer-from-1.1.2"
+      sources."bytes-1.0.0"
+      sources."callsite-1.0.0"
+      (sources."cfb-1.2.2" // {
+        dependencies = [
+          sources."adler-32-1.3.1"
+        ];
+      })
+      (sources."codepage-1.14.0" // {
+        dependencies = [
+          sources."commander-2.14.1"
+        ];
+      })
+      sources."coffee-css-0.0.5"
+      sources."coffee-script-1.12.7"
+      (sources."coffeecup-0.3.21" // {
+        dependencies = [
+          sources."uglify-js-1.2.6"
+        ];
+      })
+      sources."colors-0.6.2"
+      sources."commander-2.17.1"
+      sources."component-bind-1.0.0"
+      sources."component-emitter-1.1.2"
+      sources."component-inherit-0.0.3"
+      sources."compressible-1.1.1"
+      (sources."compression-1.0.11" // {
+        dependencies = [
+          sources."vary-1.0.1"
+        ];
+      })
+      sources."concat-stream-2.0.0"
+      sources."connect-2.25.9"
+      sources."connect-timeout-1.2.2"
+      sources."cookie-0.1.2"
+      sources."cookie-parser-1.3.2"
+      sources."cookie-signature-1.0.4"
+      sources."core-util-is-1.0.3"
+      sources."cors-2.8.5"
+      sources."crc-32-1.2.2"
+      sources."csrf-2.0.7"
+      sources."cssom-0.2.5"
+      sources."csurf-1.4.1"
+      sources."csv-parse-0.0.6"
+      sources."debug-1.0.4"
+      sources."deep-is-0.1.4"
+      sources."depd-0.4.4"
+      sources."destroy-1.0.3"
+      sources."ee-first-1.0.5"
+      sources."emitter-http://github.com/component/emitter/archive/1.0.1.tar.gz"
+      (sources."engine.io-1.3.1" // {
+        dependencies = [
+          sources."debug-0.6.0"
+        ];
+      })
+      (sources."engine.io-client-1.3.1" // {
+        dependencies = [
+          sources."debug-0.7.4"
+        ];
+      })
+      sources."engine.io-parser-1.0.6"
+      sources."errorhandler-1.1.1"
+      sources."escape-html-1.0.1"
+      sources."exit-on-epipe-1.0.1"
+      (sources."express-3.16.9" // {
+        dependencies = [
+          sources."commander-1.3.2"
+          sources."vary-0.1.0"
+        ];
+      })
+      (sources."express-session-1.7.6" // {
+        dependencies = [
+          sources."uid-safe-1.0.1"
+        ];
+      })
+      sources."fast-levenshtein-2.0.6"
+      sources."finalhandler-0.1.0"
+      sources."frac-1.1.2"
+      sources."fresh-0.2.2"
+      sources."global-https://github.com/component/global/archive/v2.0.1.tar.gz"
+      sources."graceful-readlink-1.0.1"
+      (sources."harb-0.1.1" // {
+        dependencies = [
+          sources."frac-0.3.1"
+          sources."ssf-0.8.2"
+        ];
+      })
+      sources."has-binary-data-0.1.1"
+      sources."has-cors-1.0.3"
+      sources."iconv-lite-0.4.24"
+      sources."indexof-0.0.1"
+      sources."inherits-2.0.4"
+      sources."ipaddr.js-0.1.2"
+      sources."isarray-0.0.1"
+      (sources."j-0.4.5" // {
+        dependencies = [
+          sources."adler-32-1.0.0"
+          sources."cfb-0.11.1"
+          sources."codepage-1.8.1"
+          sources."crc-32-1.0.2"
+          sources."frac-1.0.6"
+          sources."ssf-0.9.4"
+          (sources."xlsx-0.9.13" // {
+            dependencies = [
+              sources."commander-2.9.0"
+            ];
+          })
+        ];
+      })
+      sources."json3-3.2.6"
+      sources."keypress-0.1.0"
+      sources."levn-0.3.0"
+      sources."livescript-1.5.0"
+      sources."media-typer-0.2.0"
+      sources."merge-descriptors-0.0.2"
+      (sources."method-override-2.1.3" // {
+        dependencies = [
+          sources."vary-1.0.1"
+        ];
+      })
+      sources."methods-1.1.0"
+      sources."mime-1.2.11"
+      sources."mime-types-1.0.2"
+      sources."minimatch-9.0.0"
+      sources."minimist-0.0.10"
+      (sources."mkdirp-0.5.0" // {
+        dependencies = [
+          sources."minimist-0.0.8"
+        ];
+      })
+      sources."morgan-1.2.3"
+      sources."ms-0.6.2"
+      (sources."multiparty-3.3.2" // {
+        dependencies = [
+          sources."readable-stream-1.1.14"
+          sources."string_decoder-0.10.31"
+        ];
+      })
+      sources."mz-1.3.0"
+      sources."nan-0.3.2"
+      sources."native-or-bluebird-1.1.2"
+      sources."negotiator-0.4.7"
+      sources."node-uuid-1.4.1"
+      sources."object-assign-4.1.1"
+      sources."object-component-0.0.3"
+      sources."on-finished-2.1.0"
+      sources."on-headers-1.0.2"
+      sources."optimist-0.6.1"
+      sources."optionator-0.8.3"
+      sources."options-0.0.6"
+      sources."optparse-1.0.3"
+      sources."parsejson-0.0.1"
+      sources."parseqs-0.0.2"
+      sources."parseuri-0.0.2"
+      sources."parseurl-1.3.3"
+      sources."pause-0.0.1"
+      sources."prelude-ls-1.1.2"
+      sources."printj-1.1.2"
+      sources."proxy-addr-1.0.1"
+      sources."qs-2.2.2"
+      sources."range-parser-1.0.0"
+      (sources."raw-body-1.3.0" // {
+        dependencies = [
+          sources."iconv-lite-0.4.4"
+        ];
+      })
+      sources."readable-stream-3.6.2"
+      sources."redis-0.12.1"
+      sources."response-time-2.0.1"
+      sources."rndm-1.1.1"
+      sources."safe-buffer-5.2.1"
+      sources."safer-buffer-2.1.2"
+      sources."scmp-1.0.0"
+      sources."send-0.8.3"
+      sources."serve-favicon-2.0.1"
+      sources."serve-index-1.1.6"
+      (sources."serve-static-1.5.4" // {
+        dependencies = [
+          sources."send-0.8.5"
+        ];
+      })
+      sources."socialcalc-2.3.0"
+      (sources."socket.io-1.0.6" // {
+        dependencies = [
+          sources."debug-0.7.4"
+        ];
+      })
+      (sources."socket.io-adapter-0.2.0" // {
+        dependencies = [
+          sources."debug-0.7.4"
+          sources."emitter-http://github.com/component/emitter/archive/1.0.1.tar.gz"
+          sources."socket.io-parser-2.1.2"
+        ];
+      })
+      (sources."socket.io-client-1.0.6" // {
+        dependencies = [
+          sources."debug-0.7.4"
+        ];
+      })
+      (sources."socket.io-parser-2.2.0" // {
+        dependencies = [
+          sources."debug-0.7.4"
+        ];
+      })
+      sources."source-map-0.5.7"
+      sources."ssf-0.10.3"
+      (sources."stream-counter-0.2.0" // {
+        dependencies = [
+          sources."readable-stream-1.1.14"
+          sources."string_decoder-0.10.31"
+        ];
+      })
+      sources."string_decoder-1.3.0"
+      (sources."stylus-0.27.2" // {
+        dependencies = [
+          sources."mkdirp-0.3.5"
+        ];
+      })
+      sources."thenify-3.3.1"
+      sources."thenify-all-1.6.0"
+      sources."tinycolor-0.0.1"
+      sources."to-array-0.1.3"
+      sources."type-check-0.3.2"
+      sources."type-is-1.3.2"
+      sources."typedarray-0.0.6"
+      (sources."uglify-js-2.4.15" // {
+        dependencies = [
+          sources."optimist-0.3.7"
+          sources."source-map-0.1.34"
+        ];
+      })
+      sources."uglify-to-browserify-1.0.2"
+      sources."uid-safe-1.1.0"
+      sources."underscore-1.13.6"
+      sources."utf8-2.0.0"
+      sources."util-deprecate-1.0.2"
+      sources."utils-merge-1.0.0"
+      sources."uuid-pure-1.0.10"
+      sources."vary-1.1.2"
+      sources."vhost-2.0.0"
+      sources."voc-1.2.0"
+      sources."word-wrap-1.2.3"
+      sources."wordwrap-0.0.3"
+      (sources."ws-0.4.31" // {
+        dependencies = [
+          sources."commander-0.6.1"
+        ];
+      })
+      (sources."xlsjs-0.7.6" // {
+        dependencies = [
+          sources."cfb-0.11.1"
+          sources."frac-0.3.1"
+          sources."ssf-0.8.2"
+        ];
+      })
+      sources."xlsx-0.14.5"
+      sources."xmlhttprequest-https://github.com/LearnBoost/node-XMLHttpRequest/archive/0f36d0b5ebc03d85f860d42a64ae9791e1daa433.tar.gz"
+      sources."xoauth2-1.2.0"
+      sources."zappajs-0.5.0"
+    ];
+    buildInputs = globalBuildInputs;
+    meta = {
+      description = "Multi-User Spreadsheet Server";
+      homepage = "http://ethercalc.net/";
+    };
+    production = true;
+    bypassCache = true;
+    reconstructLock = true;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages.json b/nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages.json
new file mode 100644
index 000000000000..24675d73956a
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages.json
@@ -0,0 +1,3 @@
+[
+  { "whitebophir": "git+https://github.com/audreyt/ethercalc.git#b196277081d677be991d104e454a52d242ef0189" }
+]
diff --git a/nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages.nix b/nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages.nix
new file mode 100644
index 000000000000..22b4c99d08ae
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/ethercalc/node-packages.nix
@@ -0,0 +1,17 @@
+# This file has been generated by node2nix 1.11.1. Do not edit!
+
+{pkgs ? import <nixpkgs> {
+    inherit system;
+  }, system ? builtins.currentSystem, nodejs ? pkgs."nodejs_20"}:
+
+let
+  nodeEnv = import ../../../development/node-packages/node-env.nix {
+    inherit (pkgs) stdenv lib python2 runCommand writeTextFile writeShellScript;
+    inherit pkgs nodejs;
+    libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null;
+  };
+in
+import ./node-packages-generated.nix {
+  inherit (pkgs) fetchurl nix-gitignore stdenv lib fetchgit;
+  inherit nodeEnv;
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/fileshelter/default.nix b/nixpkgs/pkgs/servers/web-apps/fileshelter/default.nix
new file mode 100644
index 000000000000..337f178a1c50
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/fileshelter/default.nix
@@ -0,0 +1,33 @@
+{ lib, stdenv, fetchFromGitHub, autoreconfHook, libzip, boost, wt4, libconfig, pkg-config } :
+
+stdenv.mkDerivation rec {
+  pname = "fileshelter";
+  version = "4.0.1";
+
+  src = fetchFromGitHub {
+    owner = "epoupon";
+    repo = "fileshelter";
+    rev = "v${version}";
+    sha256 = "07n70wwqj7lqdxs3wya1m8bwg8l6lgmmlfpwyv3r3s4dfzb1b3ka";
+  };
+
+  enableParallelBuilding = true;
+
+  nativeBuildInputs = [ autoreconfHook pkg-config ];
+  buildInputs = [ libzip boost wt4 libconfig ];
+
+  NIX_LDFLAGS = "-lpthread";
+
+  postInstall = ''
+    ln -s ${wt4}/share/Wt/resources $out/share/fileshelter/docroot/resources
+  '';
+
+  meta = with lib; {
+    homepage = "https://github.com/epoupon/fileshelter";
+    description = "FileShelter is a 'one-click' file sharing web application";
+    mainProgram = "fileshelter";
+    maintainers = [ maintainers.willibutz ];
+    license = licenses.gpl3;
+    platforms = [ "x86_64-linux" ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/freshrss/default.nix b/nixpkgs/pkgs/servers/web-apps/freshrss/default.nix
new file mode 100644
index 000000000000..639a9a780c62
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/freshrss/default.nix
@@ -0,0 +1,45 @@
+{ stdenvNoCC
+, lib
+, fetchFromGitHub
+, nixosTests
+, php
+}:
+
+stdenvNoCC.mkDerivation rec {
+  pname = "FreshRSS";
+  version = "1.23.1";
+
+  src = fetchFromGitHub {
+    owner = "FreshRSS";
+    repo = "FreshRSS";
+    rev = version;
+    hash = "sha256-uidTsL8TREZ/qcqO/J+6hguP6Dr6J+995WNWCJCduBw=";
+  };
+
+  passthru.tests = {
+    inherit (nixosTests) freshrss-sqlite freshrss-pgsql freshrss-http-auth;
+  };
+
+  buildInputs = [ php ];
+
+  # There's nothing to build.
+  dontBuild = true;
+
+  postPatch = ''
+    patchShebangs cli/*.php app/actualize_script.php
+  '';
+
+  installPhase = ''
+    runHook preInstall
+    mkdir -p $out
+    cp -vr * $out/
+    runHook postInstall
+  '';
+
+  meta = with lib; {
+    description = "FreshRSS is a free, self-hostable RSS aggregator";
+    homepage = "https://www.freshrss.org/";
+    license = licenses.agpl3Plus;
+    maintainers = with maintainers; [ etu stunkymonkey ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/galene/default.nix b/nixpkgs/pkgs/servers/web-apps/galene/default.nix
new file mode 100644
index 000000000000..73503242378a
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/galene/default.nix
@@ -0,0 +1,34 @@
+{ lib, fetchFromGitHub, buildGoModule }:
+
+buildGoModule rec {
+  pname = "galene";
+  version = "0.8.1";
+
+  src = fetchFromGitHub {
+    owner = "jech";
+    repo = "galene";
+    rev = "galene-${version}";
+    hash = "sha256-CeyxeZPvClKxjEU5GYqZzV2SCyHNAktHNQbmN9wUa+4=";
+  };
+
+  vendorHash = "sha256-NT6bNVoh26I4z/QUSJWwF5YDuzf3LUc/7OQgtslc4ME=";
+
+  ldflags = [ "-s" "-w" ];
+  preCheck = "export TZ=UTC";
+
+  outputs = [ "out" "static" ];
+
+  postInstall = ''
+    mkdir $static
+    cp -r ./static $static
+  '';
+
+  meta = with lib; {
+    description = "Videoconferencing server that is easy to deploy, written in Go";
+    homepage = "https://github.com/jech/galene";
+    changelog = "https://github.com/jech/galene/raw/galene-${version}/CHANGES";
+    license = licenses.mit;
+    platforms = platforms.linux;
+    maintainers = with maintainers; [ rgrunbla erdnaxe ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/healthchecks/default.nix b/nixpkgs/pkgs/servers/web-apps/healthchecks/default.nix
new file mode 100644
index 000000000000..193452c4354c
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/healthchecks/default.nix
@@ -0,0 +1,96 @@
+{ lib
+, writeText
+, fetchFromGitHub
+, nixosTests
+, python3
+}:
+let
+  py = python3.override {
+    packageOverrides = final: prev: {
+      django = prev.django_4;
+    };
+  };
+in
+py.pkgs.buildPythonApplication rec {
+  pname = "healthchecks";
+  version = "2.10";
+  format = "other";
+
+  src = fetchFromGitHub {
+    owner = "healthchecks";
+    repo = pname;
+    rev = "refs/tags/v${version}";
+    sha256 = "sha256-1x+pYMHaKgLFWcL1axOv/ok1ebs0I7Q+Q6htncmgJzU=";
+  };
+
+  propagatedBuildInputs = with py.pkgs; [
+    apprise
+    cron-descriptor
+    cronsim
+    django
+    django-compressor
+    fido2
+    minio
+    psycopg2
+    pycurl
+    pyotp
+    segno
+    statsd
+    whitenoise
+  ];
+
+  secrets = [
+    "DB_PASSWORD"
+    "DISCORD_CLIENT_SECRET"
+    "EMAIL_HOST_PASSWORD"
+    "LINENOTIFY_CLIENT_SECRET"
+    "MATRIX_ACCESS_TOKEN"
+    "PD_APP_ID"
+    "PUSHBULLET_CLIENT_SECRET"
+    "PUSHOVER_API_TOKEN"
+    "S3_SECRET_KEY"
+    "SECRET_KEY"
+    "SLACK_CLIENT_SECRET"
+    "TELEGRAM_TOKEN"
+    "TRELLO_APP_KEY"
+    "TWILIO_AUTH"
+  ];
+
+  localSettings = writeText "local_settings.py" ''
+    import os
+
+    STATIC_ROOT = os.getenv("STATIC_ROOT")
+
+    ${lib.concatLines (map
+      (secret: ''
+        ${secret}_FILE = os.getenv("${secret}_FILE")
+        if ${secret}_FILE:
+            with open(${secret}_FILE, "r") as file:
+                ${secret} = file.readline()
+      '')
+      secrets)}
+  '';
+
+  installPhase = ''
+    mkdir -p $out/opt/healthchecks
+    cp -r . $out/opt/healthchecks
+    chmod +x $out/opt/healthchecks/manage.py
+    cp ${localSettings} $out/opt/healthchecks/hc/local_settings.py
+  '';
+
+  passthru = {
+    # PYTHONPATH of all dependencies used by the package
+    pythonPath = py.pkgs.makePythonPath propagatedBuildInputs;
+
+    tests = {
+      inherit (nixosTests) healthchecks;
+    };
+  };
+
+  meta = with lib; {
+    homepage = "https://github.com/healthchecks/healthchecks";
+    description = "A cron monitoring tool written in Python & Django ";
+    license = licenses.bsd3;
+    maintainers = with maintainers; [ phaer ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/hedgedoc/default.nix b/nixpkgs/pkgs/servers/web-apps/hedgedoc/default.nix
new file mode 100644
index 000000000000..1992c14270e7
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/hedgedoc/default.nix
@@ -0,0 +1,117 @@
+{ lib
+, stdenv
+, fetchFromGitHub
+, gitMinimal
+, cacert
+, yarn
+, makeBinaryWrapper
+, nodejs
+, python3
+, nixosTests
+}:
+
+let
+  version = "1.9.9";
+
+  src = fetchFromGitHub {
+    owner = "hedgedoc";
+    repo = "hedgedoc";
+    rev = version;
+    hash = "sha256-6eKTgEZ+YLoSmPQWBS95fJ+ioIxeTVlT+moqslByPPw=";
+  };
+
+  # we cannot use fetchYarnDeps because that doesn't support yarn 2/berry lockfiles
+  offlineCache = stdenv.mkDerivation {
+    name = "hedgedoc-${version}-offline-cache";
+    inherit src;
+
+    nativeBuildInputs = [
+      cacert # needed for git
+      gitMinimal # needed to download git dependencies
+      nodejs # needed for npm to download git dependencies
+      yarn
+    ];
+
+    buildPhase = ''
+      export HOME=$(mktemp -d)
+      yarn config set enableTelemetry 0
+      yarn config set cacheFolder $out
+      yarn config set --json supportedArchitectures.os '[ "linux" ]'
+      yarn config set --json supportedArchitectures.cpu '["arm", "arm64", "ia32", "x64"]'
+      yarn
+    '';
+
+    outputHashMode = "recursive";
+    outputHash = "sha256-Ga+tl4oZlum43tdfez1oWGMHZAfyePGl47S+9NRRvW8=";
+  };
+
+in stdenv.mkDerivation {
+  pname = "hedgedoc";
+  inherit version src;
+
+  nativeBuildInputs = [
+    makeBinaryWrapper
+    yarn
+    python3 # needed for sqlite node-gyp
+  ];
+
+  dontConfigure = true;
+
+  buildPhase = ''
+    runHook preBuild
+
+    export HOME=$(mktemp -d)
+    yarn config set enableTelemetry 0
+    yarn config set cacheFolder ${offlineCache}
+
+    # This will fail but create the sqlite3 files we can patch
+    yarn --immutable-cache || :
+
+    # Ensure we don't download any node things
+    sed -i 's:--fallback-to-build:--build-from-source --nodedir=${nodejs}/include/node:g' node_modules/sqlite3/package.json
+    export CPPFLAGS="-I${nodejs}/include/node"
+
+    # Perform the actual install
+    yarn --immutable-cache
+    yarn run build
+
+    rm bin/heroku
+    patchShebangs bin/*
+
+    runHook postBuild
+  '';
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir -p $out/share/hedgedoc
+    cp -r bin $out
+    cp -r {app.js,lib,locales,node_modules,package.json,public} $out/share/hedgedoc
+
+    for bin in $out/bin/*; do
+      wrapProgram $bin \
+        --set NODE_ENV production \
+        --set NODE_PATH "$out/share/hedgedoc/lib/node_modules"
+    done
+    makeWrapper ${nodejs}/bin/node $out/bin/hedgedoc \
+      --add-flags $out/share/hedgedoc/app.js \
+      --set NODE_ENV production \
+      --set NODE_PATH "$out/share/hedgedoc/lib/node_modules"
+
+    runHook postInstall
+  '';
+
+  passthru = {
+    inherit offlineCache;
+    tests = { inherit (nixosTests) hedgedoc; };
+  };
+
+  meta = {
+    description = "Realtime collaborative markdown notes on all platforms";
+    license = lib.licenses.agpl3Only;
+    homepage = "https://hedgedoc.org";
+    mainProgram = "hedgedoc";
+    maintainers = with lib.maintainers; [ SuperSandro2000 ];
+    platforms = lib.platforms.linux;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/invoiceplane/default.nix b/nixpkgs/pkgs/servers/web-apps/invoiceplane/default.nix
new file mode 100644
index 000000000000..8f4265cbd10b
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/invoiceplane/default.nix
@@ -0,0 +1,32 @@
+{ lib, stdenv, fetchurl, writeText, unzip, nixosTests, fetchpatch }:
+
+stdenv.mkDerivation rec {
+  pname = "invoiceplane";
+  version = "1.6.1";
+
+  src = fetchurl {
+    url = "https://github.com/InvoicePlane/InvoicePlane/releases/download/v${version}/v${version}.zip";
+    hash = "sha256-66vXxE4pTUMkmPalLgJrCt2pl2BSWOJ3tiJ5K5wspYY=";
+  };
+
+  nativeBuildInputs = [ unzip ];
+
+  sourceRoot = ".";
+
+  installPhase = ''
+    mkdir -p $out/
+    cp -r ip/. $out/
+  '';
+
+  passthru.tests = {
+    inherit (nixosTests) invoiceplane;
+  };
+
+  meta = with lib; {
+    description = "Self-hosted open source application for managing your invoices, clients and payments";
+    license = licenses.mit;
+    homepage = "https://www.invoiceplane.com";
+    platforms = platforms.all;
+    maintainers = with maintainers; [ onny ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/jirafeau/default.nix b/nixpkgs/pkgs/servers/web-apps/jirafeau/default.nix
new file mode 100644
index 000000000000..bf67125e1dab
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/jirafeau/default.nix
@@ -0,0 +1,33 @@
+{ lib, stdenv, fetchFromGitLab, writeText }:
+let
+  localConfig = writeText "config.local.php" ''
+    <?php
+      return require(getenv('JIRAFEAU_CONFIG'));
+    ?>
+  '';
+in
+stdenv.mkDerivation rec {
+  pname = "jirafeau";
+  version = "4.4.0";
+
+  src = fetchFromGitLab {
+    owner = "mojo42";
+    repo = "Jirafeau";
+    rev = version;
+    hash = "sha256-jJ2r8XTtAzawTVo2A2pDwy7Z6KHeyBkgXXaCPY0w/rg=";
+  };
+
+  installPhase = ''
+    mkdir $out
+    cp -r * $out/
+    cp ${localConfig} $out/lib/config.local.php
+  '';
+
+  meta = with lib; {
+    description = "Website permitting upload of a file in a simple way and giving a unique link to it";
+    license = licenses.agpl3Plus;
+    homepage = "https://gitlab.com/mojo42/Jirafeau";
+    platforms = platforms.all;
+    maintainers = with maintainers; [ davidtwco ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/jitsi-meet/default.nix b/nixpkgs/pkgs/servers/web-apps/jitsi-meet/default.nix
new file mode 100644
index 000000000000..c07ea1f64733
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/jitsi-meet/default.nix
@@ -0,0 +1,38 @@
+{ lib, stdenv, fetchurl, nixosTests }:
+
+stdenv.mkDerivation rec {
+  pname = "jitsi-meet";
+  version = "1.0.7790";
+
+  src = fetchurl {
+    url = "https://download.jitsi.org/jitsi-meet/src/jitsi-meet-${version}.tar.bz2";
+    sha256 = "qW3Zcrq+a1I5LABUc4uhr58E7Ig8SmrJVNdjLs0l0io=";
+  };
+
+  dontBuild = true;
+
+  installPhase = ''
+    runHook preInstall
+    mkdir $out
+    mv * $out/
+    runHook postInstall
+  '';
+
+  passthru.tests = {
+    single-host-smoke-test = nixosTests.jitsi-meet;
+  };
+
+  passthru.updateScript = ./update.sh;
+
+  meta = with lib; {
+    description = "Secure, Simple and Scalable Video Conferences";
+    longDescription = ''
+      Jitsi Meet is an open-source (Apache) WebRTC JavaScript application that uses Jitsi Videobridge
+      to provide high quality, secure and scalable video conferences.
+    '';
+    homepage = "https://github.com/jitsi/jitsi-meet";
+    license = licenses.asl20;
+    maintainers = teams.jitsi.members;
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/jitsi-meet/update.sh b/nixpkgs/pkgs/servers/web-apps/jitsi-meet/update.sh
new file mode 100755
index 000000000000..1ccf45fd1a4c
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/jitsi-meet/update.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env nix-shell
+#!nix-shell -i bash -p curl pup common-updater-scripts
+
+set -eu -o pipefail
+
+version="$(curl https://download.jitsi.org/stable/ | \
+    pup 'a[href] text{}' | \
+    awk -F'[_-]' '/jitsi-meet-web_/ {printf $4"\n"}' | \
+    sort -Vu | \
+    tail -n 1)"
+
+update-source-version jitsi-meet "$version"
diff --git a/nixpkgs/pkgs/servers/web-apps/kasmweb/default.nix b/nixpkgs/pkgs/servers/web-apps/kasmweb/default.nix
new file mode 100644
index 000000000000..f83db6baddc5
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/kasmweb/default.nix
@@ -0,0 +1,36 @@
+{ stdenv
+, lib
+, fetchzip
+}:
+
+stdenv.mkDerivation rec {
+  pname = "kasmweb";
+  version = "1.12.0";
+  build = "d4fd8a";
+
+  src = fetchzip {
+    url = "https://kasm-static-content.s3.amazonaws.com/kasm_release_${version}.${build}.tar.gz";
+    sha256 = "sha256-dCjWmI8gYtoMiMHVNgTg2ZROHXvT4ulynNvnKfMxURo=";
+  };
+
+  dontConfigure = true;
+  dontBuild = true;
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir $out
+    rm bin/utils/yq*
+    cp -r bin conf www $out/
+
+    runHook postInstall
+  '';
+
+
+  meta = with lib; {
+    homepage = "https://www.kasmweb.com/";
+    description = "Streaming containerized apps and desktops to end-users";
+    license = licenses.unfree;
+    maintainers = with maintainers; [ s1341 ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/kavita/change-webroot.diff b/nixpkgs/pkgs/servers/web-apps/kavita/change-webroot.diff
new file mode 100644
index 000000000000..a7ac56430254
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/kavita/change-webroot.diff
@@ -0,0 +1,39 @@
+diff --git a/API/Controllers/FallbackController.cs b/API/Controllers/FallbackController.cs
+index 2f5d7fce..faaf128a 100644
+--- a/API/Controllers/FallbackController.cs
++++ b/API/Controllers/FallbackController.cs
+@@ -1,4 +1,4 @@
+-using System;
++using System;
+ using System.IO;
+ using API.Services;
+ using Microsoft.AspNetCore.Authorization;
+@@ -22,7 +22,7 @@ public class FallbackController : Controller
+ 
+     public ActionResult Index()
+     {
+-        return PhysicalFile(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "index.html"), "text/HTML");
++        return PhysicalFile(Path.Combine("@web_root@", "index.html"), "text/HTML");
+     }
+ }
+ 
+diff --git a/API/Startup.cs b/API/Startup.cs
+index f84ef638..7eaeb05e 100644
+--- a/API/Startup.cs
++++ b/API/Startup.cs
+@@ -33,6 +33,7 @@ using Microsoft.AspNetCore.ResponseCompression;
+ using Microsoft.AspNetCore.StaticFiles;
+ using Microsoft.Extensions.Configuration;
+ using Microsoft.Extensions.DependencyInjection;
++using Microsoft.Extensions.FileProviders;
+ using Microsoft.Extensions.Hosting;
+ using Microsoft.Extensions.Logging;
+ using Microsoft.Net.Http.Headers;
+@@ -298,6 +299,7 @@ public class Startup
+ 
+         app.UseStaticFiles(new StaticFileOptions
+         {
++            FileProvider = new PhysicalFileProvider("@web_root@"),
+             ContentTypeProvider = new FileExtensionContentTypeProvider(),
+             HttpsCompression = HttpsCompressionMode.Compress,
+             OnPrepareResponse = ctx =>
diff --git a/nixpkgs/pkgs/servers/web-apps/kavita/default.nix b/nixpkgs/pkgs/servers/web-apps/kavita/default.nix
new file mode 100644
index 000000000000..eb9783413b4a
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/kavita/default.nix
@@ -0,0 +1,78 @@
+{ lib
+, stdenvNoCC
+, fetchFromGitHub
+, buildDotnetModule
+, buildNpmPackage
+, dotnetCorePackages
+, nixosTests
+, substituteAll
+}:
+
+stdenvNoCC.mkDerivation (finalAttrs: {
+  pname = "kavita";
+  version = "0.7.1.4";
+
+  src = fetchFromGitHub {
+    owner = "kareadita";
+    repo = "kavita";
+    rev = "v${finalAttrs.version}";
+    hash = "sha256-jNhiwyz6iVSLlvMNjI689TwQYuEvTJ+QaPvvDQ4UOwc=";
+  };
+
+  backend = buildDotnetModule {
+    pname = "kavita-backend";
+    inherit (finalAttrs) version src;
+
+    patches = [
+      # The webroot is hardcoded as ./wwwroot
+      (substituteAll {
+        src = ./change-webroot.diff;
+        web_root = "${finalAttrs.frontend}/lib/node_modules/kavita-webui/dist";
+      })
+    ];
+
+    executables = [ "API" ];
+
+    projectFile = "API/API.csproj";
+    nugetDeps = ./nuget-deps.nix;
+    dotnet-sdk = dotnetCorePackages.sdk_6_0;
+    dotnet-runtime = dotnetCorePackages.aspnetcore_6_0;
+  };
+
+  frontend =  buildNpmPackage {
+    pname = "kavita-frontend";
+    inherit (finalAttrs) version src;
+
+    sourceRoot = "${finalAttrs.src.name}/UI/Web";
+
+    npmBuildScript = "prod";
+    npmFlags = [ "--legacy-peer-deps" ];
+    npmRebuildFlags = [ "--ignore-scripts" ]; # Prevent playwright from trying to install browsers
+    npmDepsHash = "sha256-w0CuTPyCQyAxULvqd6+GiZaPlO8fh4xLmbEnGA47pL8=";
+  };
+
+  dontBuild = true;
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir -p $out/bin $out/lib/kavita
+    ln -s $backend/lib/kavita-backend $out/lib/kavita/backend
+    ln -s $frontend/lib/node_modules/kavita-webui/dist $out/lib/kavita/frontend
+    ln -s $backend/bin/API $out/bin/kavita
+
+    runHook postInstall
+  '';
+
+  passthru.tests = { inherit (nixosTests) kavita; };
+
+  meta = {
+    description = "A fast, feature rich, cross platform reading server";
+    homepage = "https://kavitareader.com";
+    changelog = "https://github.com/kareadita/kavita/releases/tag/${finalAttrs.src.rev}";
+    license = lib.licenses.gpl3Only;
+    platforms = lib.platforms.linux;
+    maintainers = with lib.maintainers; [ misterio77 ];
+    mainProgram = "kavita";
+  };
+})
diff --git a/nixpkgs/pkgs/servers/web-apps/kavita/nuget-deps.nix b/nixpkgs/pkgs/servers/web-apps/kavita/nuget-deps.nix
new file mode 100644
index 000000000000..a9c8992154be
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/kavita/nuget-deps.nix
@@ -0,0 +1,420 @@
+# This file was automatically generated by passthru.fetch-deps.
+# Please dont edit it manually, your changes might get overwritten!
+
+{ fetchNuGet }: [
+  (fetchNuGet { pname = "AutoMapper"; version = "12.0.0"; sha256 = "014r8kff1hw2k7q6979h4f333sr1lh367lmgx4iny2v3k93s7d7x"; })
+  (fetchNuGet { pname = "AutoMapper.Extensions.Microsoft.DependencyInjection"; version = "12.0.0"; sha256 = "1l17sby8l1ixn008y17wi98h74af7zmpann9kfzvqr4p0z7lg86m"; })
+  (fetchNuGet { pname = "CsvHelper"; version = "30.0.1"; sha256 = "0v01s672zcrd3fjwzh14dihbal3apzyg3dc80k05a90ljk8yh9wl"; })
+  (fetchNuGet { pname = "Docnet.Core"; version = "2.4.0-alpha.4"; sha256 = "1giv20m5gi03ybhgs10fim1k3amfc7k0iz6bwb14gw0qcnh63mhy"; })
+  (fetchNuGet { pname = "DotNet.Glob"; version = "3.1.3"; sha256 = "1klgj9m7i3g8x1yj96wnikvf0hlvr6rhqhl4mgis08imcrl95qg6"; })
+  (fetchNuGet { pname = "ExCSS"; version = "4.1.0"; sha256 = "1dbnl1dgkkwcrls9nw63xsjph14f3xx134dksbcjak3k3ynbnl6v"; })
+  (fetchNuGet { pname = "Flurl"; version = "3.0.6"; sha256 = "1y82lbag0gkfpj361psk5761hn7k0zmrp9cpdvnjyp75bdimiaiy"; })
+  (fetchNuGet { pname = "Flurl.Http"; version = "3.2.4"; sha256 = "0vp5a1rrfi28in775d7fac96rcrikzjd2gbz0k3p925y1f2wlw5k"; })
+  (fetchNuGet { pname = "Hangfire"; version = "1.7.31"; sha256 = "1c02nrg16pm5aypvlnddyj6zds4sj59qrhc980d9y5gf7nx72kjl"; })
+  (fetchNuGet { pname = "Hangfire.AspNetCore"; version = "1.7.31"; sha256 = "0shfgqphjyb61djvrssnf2npbid236lbdpfvsznsl5hga9x3bdah"; })
+  (fetchNuGet { pname = "Hangfire.Core"; version = "1.6.1"; sha256 = "0rg4lzzckscck9gvjqhcn1yq9qymfs4dfkv6fwgnklyfpvxmsqbq"; })
+  (fetchNuGet { pname = "Hangfire.Core"; version = "1.6.17"; sha256 = "0kr2hjnl9c4dpk4kf95jxcgsxalvixfm6xis37qn5ja9n9ygqans"; })
+  (fetchNuGet { pname = "Hangfire.Core"; version = "1.7.0"; sha256 = "0yy9z7zssqysyp73phg6p5p1lva56d1vh9r825dn6w26jxdrlz21"; })
+  (fetchNuGet { pname = "Hangfire.Core"; version = "1.7.31"; sha256 = "13jfgd9x7a63yqs0b7y9jnkwi1jwq7h2mp8cxp0bzn3xk8w45kqi"; })
+  (fetchNuGet { pname = "Hangfire.Core"; version = "1.7.6"; sha256 = "19rfwpq714fybxara6vsr3r0h0wgnzrrvhqlhprh5lvgv15z9glm"; })
+  (fetchNuGet { pname = "Hangfire.InMemory"; version = "0.3.4"; sha256 = "1afrvxw6z0a78wrrv4mzrn86pvwr9zy97cwfs2k7s1aq5wp655r8"; })
+  (fetchNuGet { pname = "Hangfire.MaximumConcurrentExecutions"; version = "1.1.0"; sha256 = "181147h5dsbml58ffq1jc7k6012fahi0n20wply9gmn6v1dh8h66"; })
+  (fetchNuGet { pname = "Hangfire.MemoryStorage.Core"; version = "1.4.0"; sha256 = "1hw8dlclxgg21ay1pqj9mxxm3alm03k9wxaz055lb14w3nzyma3c"; })
+  (fetchNuGet { pname = "Hangfire.SqlServer"; version = "1.7.31"; sha256 = "1hjln8jnp3ysv525c7cm31z0jpxgvncn3isi57mjalax0pjsl5hb"; })
+  (fetchNuGet { pname = "Hangfire.Storage.SQLite"; version = "0.3.2"; sha256 = "05w8la0zyh6lvgw98lwh1jaqxj0h9720jz5fc3bl4gaxnxfw17y2"; })
+  (fetchNuGet { pname = "HtmlAgilityPack"; version = "1.11.46"; sha256 = "0yx0xgbbzd6fdyslf7pc37bxk4hfkj1c7359ibqwmapv9aby7lm2"; })
+  (fetchNuGet { pname = "Humanizer.Core"; version = "2.8.26"; sha256 = "1v8xd12yms4qq1md4vh6faxicmqrvahqdd7sdkyzrphab9v44nsm"; })
+  (fetchNuGet { pname = "MarkdownDeep.NET.Core"; version = "1.5.0.4"; sha256 = "0cpshs1lwmyyg40lvnf4b9s1z7yaw6s4a0341qr4ww40791gzvrl"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.App.Ref"; version = "6.0.16"; sha256 = "1v02j1i139a8x32hgi1yhcpp754xi0sg5b7iqzmslvinfg3b7dwn"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64"; version = "6.0.16"; sha256 = "0c6ys204024yi6wh6jyyvkv60f877nzlmzl6np30w9a3nxlavnhw"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.App.Runtime.linux-x64"; version = "6.0.16"; sha256 = "1xdhn8v8y947kw29npck1h9qaw8rj81q7a0qwawpc2200ds96n40"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64"; version = "6.0.16"; sha256 = "1p84za2cxyxxbkgxhfnmdarkz64dacx9f52jplrfs9rgl19anan4"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.App.Runtime.osx-x64"; version = "6.0.16"; sha256 = "1i26fssv17w3kcaqwk5w2aq03jdijhrfl0xp0q5s68j7i4wrlv6l"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Authentication.Abstractions"; version = "2.2.0"; sha256 = "0vj7fhpk0d95nkkxz4q0rma6pb4ym96mx6nms4603y0l19h0k5yh"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Authentication.JwtBearer"; version = "6.0.10"; sha256 = "0prhz63lakq9vihdppb6k1q9ix2crzbcfpkxbks698cirh9pbxmn"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Authentication.OpenIdConnect"; version = "6.0.10"; sha256 = "0vpw55k7w2ha9nrffabq4mhik54y93bbf9hk99klaxnirnxhrjqh"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Authorization"; version = "2.2.0"; sha256 = "1mpq8pmxlxfa625k2ghv6xcyy2wdpwv56xzya9mvmlnh50h1i8rx"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Authorization.Policy"; version = "2.2.0"; sha256 = "1d1zh65kfjf81j21ssmhr465vx08bra8424vgnrb22gdx03mhwd2"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Connections.Abstractions"; version = "2.2.0"; sha256 = "1rl94r8b0zq14f3dhfnvfjj1ivr81iw9zh5kdgs3zkdv0xc9x21j"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Cryptography.Internal"; version = "6.0.10"; sha256 = "1jlhgrzm4pv9yigif1khrqkc7hk4v8lz657hfiqvvih32xm13c1w"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Cryptography.KeyDerivation"; version = "6.0.10"; sha256 = "1k6j5mm7cbqljr0x6qks0359r5r33mw4a0mpanfqc1sd3i3x465y"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Hosting.Abstractions"; version = "2.2.0"; sha256 = "043k651vbfshh3s997x42ymj8nb32419m7q3sjw5q2c27anrhfhv"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Hosting.Server.Abstractions"; version = "2.2.0"; sha256 = "0nz73bwrvhc1n7gd7xxm3p5ww2wx9qr9m9i43y20gh0c54adkygh"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Http"; version = "2.2.0"; sha256 = "1fcrafpa57sab3as18idqknzlxkx49n4sxzlzik3sj6pcji5j17q"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Http.Abstractions"; version = "2.2.0"; sha256 = "13s8cm6jdpydxmr0rgmzrmnp1v2r7i3rs7v9fhabk5spixdgfy6b"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Http.Connections"; version = "1.1.0"; sha256 = "03wh8cl2ar3v6v3j7ysif680wqy1wgzmcfrzrcsy16fn8y73dylq"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Http.Connections.Common"; version = "1.1.0"; sha256 = "0x3hq0d3bs6n46nfvbd5n4cgi6m4yjfsf3k25xjcc8gcj66072iy"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Http.Extensions"; version = "2.2.0"; sha256 = "118gp1mfb8ymcvw87fzgjqwlc1d1b0l0sbfki291ydg414cz3dfn"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Http.Features"; version = "2.2.0"; sha256 = "0xrlq8i61vzhzzy25n80m7wh2kn593rfaii3aqnxdsxsg6sfgnx1"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Identity.EntityFrameworkCore"; version = "6.0.10"; sha256 = "0zdgc7336lh562p8cy03wk8aawk5ngyzgbalbrqfbzf4graawsna"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Routing"; version = "2.2.0"; sha256 = "12kv602j2rxp43l1v3618yz3pdd7hqc3r98ya0bqz6y2ppvhbyws"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Routing.Abstractions"; version = "2.2.0"; sha256 = "0d9wwz1rsh1fslbv1y72jpkvqv2v9n28rl3vslcg0x74lp2678ly"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.SignalR"; version = "1.1.0"; sha256 = "16p01hxcrpj7iiwcqmwjfmciyisxp1mr0qa1wcx1ja4i0m0g292l"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.SignalR.Common"; version = "1.1.0"; sha256 = "0gfcq6wg7ygkb7l9y8avx88gilpds58p2vb8sqd7xmgm6616saax"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.SignalR.Core"; version = "1.1.0"; sha256 = "1lrya5f6nzimx43vwywrrl7jvg1rm0gdigqmg1z52wbllb7jpmph"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.SignalR.Protocols.Json"; version = "1.1.0"; sha256 = "0zcyb3brzpw03f7vgkc3450izpvjgy0kjkgkp1mi9bc76xrvv094"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.WebSockets"; version = "2.2.0"; sha256 = "0hii6kd45xhswjwakhzm8wqxr10l959cch6h2w0x0ika3315a6b3"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.WebUtilities"; version = "2.2.0"; sha256 = "0cs1g4ing4alfbwyngxzgvkrv7z964isv1j9dzflafda4p0wxmsi"; })
+  (fetchNuGet { pname = "Microsoft.CSharp"; version = "4.0.1"; sha256 = "0zxc0apx1gcx361jlq8smc9pfdgmyjh6hpka8dypc9w23nlsh6yj"; })
+  (fetchNuGet { pname = "Microsoft.CSharp"; version = "4.5.0"; sha256 = "01i28nvzccxbqmiz217fxs6hnjwmd5fafs37rd49a6qp53y6623l"; })
+  (fetchNuGet { pname = "Microsoft.CSharp"; version = "4.7.0"; sha256 = "0gd67zlw554j098kabg887b5a6pq9kzavpa3jjy5w53ccjzjfy8j"; })
+  (fetchNuGet { pname = "Microsoft.Data.Sqlite.Core"; version = "6.0.10"; sha256 = "1sdh5rw2pyg6c64z0haxf57bakd5kwaav624vlqif1m59iz26rag"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore"; version = "6.0.10"; sha256 = "014varyy877kxzgqp9bl9l81avz8dr34hn4ad23qr17lvllchk95"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore.Abstractions"; version = "6.0.10"; sha256 = "1w93zr8z1f3yn6ygxnlbly8spz3jr77v0h9ky596gpvfg46wi5fd"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore.Analyzers"; version = "6.0.10"; sha256 = "0wvkgrmxgjnqv2kc69n44wsy129f09951a8dh7d4vjbi5f5jcx12"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore.Design"; version = "6.0.10"; sha256 = "0pwah00gbm7rycsvjp4yaph9wjxnh14lzlds2r8v2smw0zwzp9da"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore.Relational"; version = "6.0.10"; sha256 = "11b2ibj5sgj8mm708vm9ar8vqgzsx9j4rsxzzn3xnrqbjvfxpjal"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore.Sqlite"; version = "6.0.10"; sha256 = "0hv70ns69rgf029219jkasrw16j8609gnmi1zk7v2wgm8pxdsjdy"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore.Sqlite.Core"; version = "6.0.10"; sha256 = "1s1wj12maw6kzfxzh1j2wrx5m1vwcsc411jq6zklqvrbw0r0ylyc"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.ApiDescription.Server"; version = "6.0.5"; sha256 = "1pi2bm3cm0a7jzqzmfc2r7bpcdkmk3hhjfvb2c81j7wl7xdw3624"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Caching.Abstractions"; version = "6.0.0"; sha256 = "0qn30d3pg4rx1x2k525jj4x5g1fxm2v5m0ksz2dmk1gmqalpask8"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Caching.Memory"; version = "6.0.1"; sha256 = "0ra0ldbg09r40jzvfqhpb3h42h80nafvka9hg51dja32k3mxn5gk"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration"; version = "2.0.0"; sha256 = "0yssxq9di5h6xw2cayp5hj3l9b2p0jw9wcjz73rwk4586spac9s9"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration"; version = "6.0.0"; sha256 = "1zdyai2rzngmsp3706d12qrdk315c1s3ja218fzb3nc3wd1vz0s8"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Abstractions"; version = "2.0.0"; sha256 = "1ilz2yrgg9rbjyhn6a5zh9pr51nmh11z7sixb4p7vivgydj9gxwf"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Abstractions"; version = "2.2.0"; sha256 = "1fv5277hyhfqmc0gqszyqb1ilwnijm8kc9606yia6hwr8pxyg674"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Abstractions"; version = "3.1.8"; sha256 = "05mlbia6vag0a0zfflv1m3ix48230wx0yib5hp7zsc72jpcmjd7q"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Abstractions"; version = "6.0.0"; sha256 = "0w6wwxv12nbc3sghvr68847wc9skkdgsicrz3fx4chgng1i3xy0j"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Binder"; version = "2.0.0"; sha256 = "1prvdbma6r18n5agbhhabv6g357p1j70gq4m9g0vs859kf44nrgc"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Binder"; version = "6.0.0"; sha256 = "15hb2rbzgri1fq8wpj4ll7czm3rxqzszs02phnhjnncp90m5rmpc"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.CommandLine"; version = "6.0.0"; sha256 = "1hb4qrq9xdxzh2px515pv1vkz1jigwaxw1hfg9w8s6pgl8z04l4c"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.EnvironmentVariables"; version = "6.0.1"; sha256 = "16xpqfzpcjk3mg70g5g2qrkhqf7rppah3q6dasdddbpikw43ni47"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.FileExtensions"; version = "6.0.0"; sha256 = "02nna984iwnyyz4jjh9vs405nlj0yk1g5vz4v2x30z2c89mx5f9w"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Json"; version = "6.0.0"; sha256 = "1c6l5szma1pdn61ncq1kaqibg0dz65hbma2xl626a8d1m6awn353"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.UserSecrets"; version = "6.0.1"; sha256 = "0faddzvkhjhsn9fp269r4sapjrahiynwlwakhzljfg3k94jfldk1"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection"; version = "6.0.0"; sha256 = "1wlhb2vygzfdjbdzy7waxblmrx0q3pdcqvpapnpmq9fcx5m8r6w1"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection"; version = "6.0.1"; sha256 = "0kl5ypidmzllyxb91gwy3z950dc416p1y8wikzbdbp0l7aaaxq2p"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "2.0.0"; sha256 = "1pwrfh9b72k9rq6mb2jab5qhhi225d5rjalzkapiayggmygc8nhz"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "2.2.0"; sha256 = "1jyzfdr9651h3x6pxwhpfbb9mysfh8f8z1jvy4g117h9790r9zx5"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "3.1.8"; sha256 = "1vkhhyxpam3svbqkkxrcxh9h4r6h3vm76cdzmfqn7gbxgswc4y2w"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "3.1.9"; sha256 = "1l7ng71y18fwdlyq2ycl12hmv9wrf7k7knz2jwv9w9w7spmp8jv6"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "5.0.0"; sha256 = "17cz6s80va0ch0a6nqa1wbbbp3p8sqxb96lj4qcw67ivkp2yxiyj"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "6.0.0"; sha256 = "1vi67fw7q99gj7jd64gnnfr4d2c0ijpva7g9prps48ja6g91x6a9"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyModel"; version = "3.0.0"; sha256 = "1cm0hycgb33mf1ja9q91wxi3gk13d1p462gdq7gndrya23hw2jm5"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyModel"; version = "3.1.6"; sha256 = "13m2na8a5mglbbjjp0dxb8ifkf23grkyk1g8585mr7v6cbj098ac"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyModel"; version = "6.0.0"; sha256 = "08c4fh1n8vsish1vh7h73mva34g0as4ph29s4lvps7kmjb4z64nl"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.FileProviders.Abstractions"; version = "2.2.0"; sha256 = "1f83ffb4xjwljg8dgzdsa3pa0582q6b4zm0si467fgkybqzk3c54"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.FileProviders.Abstractions"; version = "3.1.8"; sha256 = "0z173lsfypzjdx1a352svh1pgk7lgq2wpj5q60i1rgcrd3ib8b21"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.FileProviders.Abstractions"; version = "6.0.0"; sha256 = "1fbqmfapxdz77drcv1ndyj2ybvd2rv4c9i9pgiykcpl4fa6dc65q"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.FileProviders.Physical"; version = "6.0.0"; sha256 = "1ikc3kf325xig6njbi2aj5kmww4xlaq9lsrpc8v764fsm4x10474"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.FileSystemGlobbing"; version = "6.0.0"; sha256 = "09gyyv4fwy9ys84z3aq4lm9y09b7bd1d4l4gfdinmg0z9678f1a4"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Hosting"; version = "6.0.1"; sha256 = "11jwzzyryr6i2nwfcrs4rjv4qg0zmm15gaa882xk54ric3zc37ig"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Hosting.Abstractions"; version = "2.2.0"; sha256 = "1xc7xr1nq7akfahyl5in9iyxrygap2xi9nxh39rfm37sf8lk55v1"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Hosting.Abstractions"; version = "3.1.8"; sha256 = "1lc69rn259gd6y4rjy0hwrcfnhkr0y0ac8w4ldh6mpk073snfjq0"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Hosting.Abstractions"; version = "6.0.0"; sha256 = "1mwjx6li4a82nb589763whpnhf5hfy1bpv1dzqqvczb1lhxhzhlj"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Identity.Core"; version = "6.0.10"; sha256 = "1cqp9adfc0nzakykqdj7v2842sys910k64pmnklc2jrdn5chphba"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Identity.Stores"; version = "6.0.10"; sha256 = "01kzmgbyii2sxi89iv7fjvk1crqcnzkz7m6dvfjnhgx479fm8g68"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging"; version = "2.0.0"; sha256 = "1jkwjcq1ld9znz1haazk8ili2g4pzfdp6i7r7rki4hg3jcadn386"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging"; version = "5.0.0"; sha256 = "1qa1l18q2jh9azya8gv1p8anzcdirjzd9dxxisb4911i9m1648i3"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging"; version = "6.0.0"; sha256 = "0fd9jii3y3irfcwlsiww1y9npjgabzarh33rn566wpcz24lijszi"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "2.0.0"; sha256 = "1x5isi71z02khikzvm7vaschb006pqqrsv86ky1x08a4hir4s43h"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "2.2.0"; sha256 = "02w7hp6jicr7cl5p456k2cmrjvvhm6spg5kxnlncw3b72358m5wl"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "3.1.8"; sha256 = "0iq8py91xvma10rysq3dl29nxhmlgniad3cvafb4jg8iz52ym24h"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "5.0.0"; sha256 = "1yza38675dbv1qqnnhqm23alv2bbaqxp0pb7zinjmw8j2mr5r6wc"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "6.0.0"; sha256 = "0b75fmins171zi6bfdcq1kcvyrirs8n91mknjnxy4c3ygi1rrnj0"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Configuration"; version = "2.0.0"; sha256 = "1kndzxrbxd6hh6zpas25xx096q2lablrdx5di79vsmkxf65996a9"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Configuration"; version = "6.0.0"; sha256 = "0plx785hk61arjxf0m3ywy9hl5nii25raj4523n3ql7mmv6hxqr1"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Console"; version = "6.0.0"; sha256 = "1383b0r33dzz0hrch9cqzzxr9vxr21qq0a5vnrpkfq71m2fky31d"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Debug"; version = "6.0.0"; sha256 = "0aql9kc45g2d6z1hmwr3p1a2qy9m3f36bds3054givsnpnis81wk"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.EventLog"; version = "6.0.0"; sha256 = "0j3g2k8sr99kr73w66yk4ghq469syyxzayq6fjfnjjgj1y7x05fl"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.EventSource"; version = "6.0.0"; sha256 = "0ck8r63qal88349kkbj1i98fd8z9kcp41s13yyz8cpkygn15wq4g"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.ObjectPool"; version = "2.2.0"; sha256 = "0n1q9lvc24ii1shzy575xldgmz7imnk4dswwwcgmzz93klri9r1z"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options"; version = "2.0.0"; sha256 = "0g4zadlg73f507krilhaaa7h0jdga216syrzjlyf5fdk25gxmjqh"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options"; version = "2.2.0"; sha256 = "1b20yh03fg4nmmi3vlf6gf13vrdkmklshfzl3ijygcs4c2hly6v0"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options"; version = "5.0.0"; sha256 = "1rdmgpg770x8qwaaa6ryc27zh93p697fcyvn5vkxp0wimlhqkbay"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options"; version = "6.0.0"; sha256 = "008pnk2p50i594ahz308v81a41mbjz9mwcarqhmrjpl2d20c868g"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options.ConfigurationExtensions"; version = "2.0.0"; sha256 = "1isc3rjbzz60f7wbmgcwslx5d10hm5hisnk7v54vfi2bz7132gll"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options.ConfigurationExtensions"; version = "6.0.0"; sha256 = "1k6q91vrhq1r74l4skibn7wzxzww9l74ibxb2i8gg4q6fzbiivba"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Primitives"; version = "2.0.0"; sha256 = "1xppr5jbny04slyjgngxjdm0maxdh47vq481ps944d7jrfs0p3mb"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Primitives"; version = "2.2.0"; sha256 = "0znah6arbcqari49ymigg3wiy2hgdifz8zsq8vdc3ynnf45r7h0c"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Primitives"; version = "3.1.8"; sha256 = "1p48hk3r9ikv36wdpwdrbvaccziazncf7nl60fr82i04199lfhgl"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Primitives"; version = "5.0.0"; sha256 = "0swqcknyh87ns82w539z1mvy804pfwhgzs97cr3nwqk6g5s42gd6"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Primitives"; version = "6.0.0"; sha256 = "1kjiw6s4yfz9gm7mx3wkhp06ghnbs95icj9hi505shz9rjrg42q2"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Abstractions"; version = "6.24.0"; sha256 = "06hdlj8j3ckhr2jglcfwmazlqbcnwqb10c86vwnwmiv6czrl9m2b"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.JsonWebTokens"; version = "6.24.0"; sha256 = "1lxfbjcvqdk9aircy30jrwsjfr0dwn334shis0k3x0qag3ynp180"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Logging"; version = "6.10.0"; sha256 = "0fg742czl8rz6ljh6gscv6sck2f8dfgrig3j76ihzrnayd0hjvyf"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Logging"; version = "6.24.0"; sha256 = "07l8hfpd50gab12s8xiad8wi4ggr6v3pmv7b0zbff6i9yshp0lgj"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Protocols"; version = "6.10.0"; sha256 = "17cm3xpkp5rvfcx5d8bnsgc1mq52ky1fxv1h48dk1nafkkijg3zq"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Protocols.OpenIdConnect"; version = "6.10.0"; sha256 = "18n9d5qywvv5jc0iryxfasy3lwknf1zv76hz64656x39aprwdmm3"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Tokens"; version = "6.10.0"; sha256 = "1qlg5snjxzgwx7lwkszl6aziyzs2jbsr0xvbn1lhq2lq7gl07khy"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Tokens"; version = "6.24.0"; sha256 = "1rgxi6jkhm8nj8yby65v1b6x8fp655b92w2y7ly2fj385s0d5qgy"; })
+  (fetchNuGet { pname = "Microsoft.IO.RecyclableMemoryStream"; version = "2.2.1"; sha256 = "1nz1cv5dz0bg9snzig6fyaidb92b4ynfljj7l34vnqc9xbnqxv83"; })
+  (fetchNuGet { pname = "Microsoft.Net.Http.Headers"; version = "2.2.0"; sha256 = "0w6lrk9z67bcirq2cj2ldfhnizc6id77ba6i30hjzgqjlyhh1gx5"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.App.Host.linux-arm64"; version = "6.0.16"; sha256 = "0iv5186gb778swka9ylzblwvr8pp7cmsvji5iiszrnfvk8c4n3ia"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.App.Host.linux-x64"; version = "6.0.16"; sha256 = "1pv9arqbmxlh86rnx6nss2cl91hi22j83p66m4ahds34caykf32l"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.App.Host.osx-arm64"; version = "6.0.16"; sha256 = "01f98kkq8p3xll4mh6ck8ljgs3k5psv5z7mys7kpvk7lvag2svaa"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.App.Host.osx-x64"; version = "6.0.16"; sha256 = "19ffmw131b8kv7l5pmwi4358j5xhla48qdyn6jv9fznffcsxfgzc"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.App.Ref"; version = "6.0.16"; sha256 = "1w89n5grnxdis0wclfimi9ij8g046yrw76rhmcp8l57xm8nl21yj"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.App.Runtime.linux-arm64"; version = "6.0.16"; sha256 = "10dlkzk61nnnw6f5rr1lmrws2p4hvbpkswm3209w45z350n9nlpy"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.App.Runtime.linux-x64"; version = "6.0.16"; sha256 = "1fjrc1l7ihal93ybxqzlxrs7vdqb9jhkabh2acwrmlh7q5197vn2"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.App.Runtime.osx-arm64"; version = "6.0.16"; sha256 = "0jsfjp32z08pgi82blcrhmf5ipkhlg1kld8jmr7znzgv0kic8xyh"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.App.Runtime.osx-x64"; version = "6.0.16"; sha256 = "0gghxcr32mri7235f41w5ngdxrw85q28nd7d57hmzj72cv93yxb3"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Jit"; version = "1.0.2"; sha256 = "0jaan2wmg80lr0mhgfy70kb5cqjwv1a2ikmxgd0glpcxp7wr7pag"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Platforms"; version = "1.0.1"; sha256 = "01al6cfxp68dscl15z7rxfw9zvhm64dncsw09a1vmdkacsa2v6lr"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Platforms"; version = "1.1.0"; sha256 = "08vh1r12g6ykjygq5d3vq09zylgb84l63k49jc4v8faw9g93iqqm"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Platforms"; version = "2.0.0"; sha256 = "1fk2fk2639i7nzy58m9dvpdnzql4vb8yl8vr19r2fp8lmj9w2jr0"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Platforms"; version = "2.1.2"; sha256 = "1507hnpr9my3z4w1r6xk5n0s1j3y6a2c2cnynj76za7cphxi1141"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Platforms"; version = "5.0.0"; sha256 = "0mwpwdflidzgzfx2dlpkvvnkgkr2ayaf0s80737h4wa35gaj11rc"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Portable.Compatibility"; version = "1.0.1"; sha256 = "1qwar1jv2pwl354bbi75rvcjz27rrk0z0vzgx8h4f1ypn2m5h3f5"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Runtime.CoreCLR"; version = "1.0.2"; sha256 = "1hxgsjyzh7hdgd34xwpn5s2myy1b1y9ms7xhvs6mkb75wap49bpc"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Targets"; version = "1.0.1"; sha256 = "0ppdkwy6s9p7x9jix3v4402wb171cdiibq7js7i13nxpdky7074p"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Targets"; version = "1.1.0"; sha256 = "193xwf33fbm0ni3idxzbr5fdq3i2dlfgihsac9jj7whj0gd902nh"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Windows.ApiSets"; version = "1.0.1"; sha256 = "16k8chghkr25jf49banhzl839vs8n3vbfpg4wn4idi0hzjipix78"; })
+  (fetchNuGet { pname = "Microsoft.OpenApi"; version = "1.2.3"; sha256 = "07b19k89whj69j87afkz86gp9b3iybw8jqwvlgcn43m7fb2y99rr"; })
+  (fetchNuGet { pname = "Microsoft.OpenApi"; version = "1.3.1"; sha256 = "0icds4jxz90v156vkbza1s1rqdf737glfddbllkp6y2zcnin99yv"; })
+  (fetchNuGet { pname = "Microsoft.Win32.Primitives"; version = "4.0.1"; sha256 = "1n8ap0cmljbqskxpf8fjzn7kh1vvlndsa75k01qig26mbw97k2q7"; })
+  (fetchNuGet { pname = "Microsoft.Win32.Primitives"; version = "4.3.0"; sha256 = "0j0c1wj4ndj21zsgivsc24whiya605603kxrbiw6wkfdync464wq"; })
+  (fetchNuGet { pname = "Microsoft.Win32.Registry"; version = "4.4.0"; sha256 = "088j2anh1rnkxdcycw5kgp97ahk7cj741y6kask84880835arsb6"; })
+  (fetchNuGet { pname = "Microsoft.Win32.SystemEvents"; version = "6.0.0"; sha256 = "0c6pcj088g1yd1vs529q3ybgsd2vjlk5y1ic6dkmbhvrp5jibl9p"; })
+  (fetchNuGet { pname = "NETStandard.Library"; version = "1.6.0"; sha256 = "0nmmv4yw7gw04ik8ialj3ak0j6pxa9spih67hnn1h2c38ba8h58k"; })
+  (fetchNuGet { pname = "NETStandard.Library"; version = "1.6.1"; sha256 = "1z70wvsx2d847a2cjfii7b83pjfs34q05gb037fdjikv5kbagml8"; })
+  (fetchNuGet { pname = "NetVips"; version = "2.2.0"; sha256 = "10hqqzd84qa0yn9zcyzv8mcjh6g7g0xv0fc4binh92zw9a4g542p"; })
+  (fetchNuGet { pname = "NetVips.Native"; version = "8.13.1"; sha256 = "0yxci6zffy8kaz8dg85b2qw8zcjswmm56m5bvxaha1khbx1vpkz3"; })
+  (fetchNuGet { pname = "NetVips.Native.linux-arm"; version = "8.13.1"; sha256 = "0ypz0qslkmcd62n7z3y4yq16f9ybbnvka16bk7h72cv6bsdw9hzp"; })
+  (fetchNuGet { pname = "NetVips.Native.linux-arm64"; version = "8.13.1"; sha256 = "0wvh7rl1c56ipa1i6rh6nq80wvvl5bz2wswk219lyb2psd0vza3f"; })
+  (fetchNuGet { pname = "NetVips.Native.linux-musl-arm64"; version = "8.13.1"; sha256 = "0gj92wg76ynfx0kz8z26mg67aclyz0yn6xxp0g5mlj09kscbmikx"; })
+  (fetchNuGet { pname = "NetVips.Native.linux-musl-x64"; version = "8.13.1"; sha256 = "13hf0mij2gryn00701msamq5ijrdgv080ipm50gz80vb09l3ra2s"; })
+  (fetchNuGet { pname = "NetVips.Native.linux-x64"; version = "8.13.1"; sha256 = "1yx3mrp9n85fqpkgn43fv8ah9rcv301cn3ngkzy54rzlmlmf0qr2"; })
+  (fetchNuGet { pname = "NetVips.Native.osx-arm64"; version = "8.13.1"; sha256 = "1ifh9ic2g91kwsz7p1g4icw36rs0hjnd8dr1ahgrdb4nh5ap3vcc"; })
+  (fetchNuGet { pname = "NetVips.Native.osx-x64"; version = "8.13.1"; sha256 = "0ksgydiv8d63brsg2wkpc2dv88yz3kw2zzx0i0gfnwwn7vxsv1k9"; })
+  (fetchNuGet { pname = "NetVips.Native.win-arm64"; version = "8.13.1"; sha256 = "1qzfz5wys81dmf4v4l4gmx8syx7x26450fwp2dc8fh4m33910dqr"; })
+  (fetchNuGet { pname = "NetVips.Native.win-x64"; version = "8.13.1"; sha256 = "02x7n14w2iff5xvp340yc4j810mk3hnd8z8vl604r3ywwbaaykn2"; })
+  (fetchNuGet { pname = "NetVips.Native.win-x86"; version = "8.13.1"; sha256 = "1lzrqvmxqbm0y897bavl7pmfn2ywpjw6arfvj0v5i84y7glrp981"; })
+  (fetchNuGet { pname = "Newtonsoft.Json"; version = "11.0.1"; sha256 = "1z68j07if1xf71lbsrgbia52r812i2dv541sy44ph4dzjjp7pd4m"; })
+  (fetchNuGet { pname = "Newtonsoft.Json"; version = "11.0.2"; sha256 = "1784xi44f4k8v1fr696hsccmwpy94bz7kixxqlri98zhcxn406b2"; })
+  (fetchNuGet { pname = "Newtonsoft.Json"; version = "12.0.2"; sha256 = "0w2fbji1smd2y7x25qqibf1qrznmv4s6s0jvrbvr6alb7mfyqvh5"; })
+  (fetchNuGet { pname = "Newtonsoft.Json"; version = "9.0.1"; sha256 = "0mcy0i7pnfpqm4pcaiyzzji4g0c8i3a5gjz28rrr28110np8304r"; })
+  (fetchNuGet { pname = "NReco.Logging.File"; version = "1.1.5"; sha256 = "1chvzhyvlnqswa1r1vbnk4h0as2f2dba3dnsldmmck7pb0vaj673"; })
+  (fetchNuGet { pname = "runtime.any.System.Collections"; version = "4.3.0"; sha256 = "0bv5qgm6vr47ynxqbnkc7i797fdi8gbjjxii173syrx14nmrkwg0"; })
+  (fetchNuGet { pname = "runtime.any.System.Diagnostics.Tools"; version = "4.3.0"; sha256 = "1wl76vk12zhdh66vmagni66h5xbhgqq7zkdpgw21jhxhvlbcl8pk"; })
+  (fetchNuGet { pname = "runtime.any.System.Diagnostics.Tracing"; version = "4.3.0"; sha256 = "00j6nv2xgmd3bi347k00m7wr542wjlig53rmj28pmw7ddcn97jbn"; })
+  (fetchNuGet { pname = "runtime.any.System.Globalization"; version = "4.3.0"; sha256 = "1daqf33hssad94lamzg01y49xwndy2q97i2lrb7mgn28656qia1x"; })
+  (fetchNuGet { pname = "runtime.any.System.Globalization.Calendars"; version = "4.3.0"; sha256 = "1ghhhk5psqxcg6w88sxkqrc35bxcz27zbqm2y5p5298pv3v7g201"; })
+  (fetchNuGet { pname = "runtime.any.System.IO"; version = "4.3.0"; sha256 = "0l8xz8zn46w4d10bcn3l4yyn4vhb3lrj2zw8llvz7jk14k4zps5x"; })
+  (fetchNuGet { pname = "runtime.any.System.Reflection"; version = "4.3.0"; sha256 = "02c9h3y35pylc0zfq3wcsvc5nqci95nrkq0mszifc0sjx7xrzkly"; })
+  (fetchNuGet { pname = "runtime.any.System.Reflection.Extensions"; version = "4.3.0"; sha256 = "0zyri97dfc5vyaz9ba65hjj1zbcrzaffhsdlpxc9bh09wy22fq33"; })
+  (fetchNuGet { pname = "runtime.any.System.Reflection.Primitives"; version = "4.3.0"; sha256 = "0x1mm8c6iy8rlxm8w9vqw7gb7s1ljadrn049fmf70cyh42vdfhrf"; })
+  (fetchNuGet { pname = "runtime.any.System.Resources.ResourceManager"; version = "4.3.0"; sha256 = "03kickal0iiby82wa5flar18kyv82s9s6d4xhk5h4bi5kfcyfjzl"; })
+  (fetchNuGet { pname = "runtime.any.System.Runtime"; version = "4.3.0"; sha256 = "1cqh1sv3h5j7ixyb7axxbdkqx6cxy00p4np4j91kpm492rf4s25b"; })
+  (fetchNuGet { pname = "runtime.any.System.Runtime.Handles"; version = "4.3.0"; sha256 = "0bh5bi25nk9w9xi8z23ws45q5yia6k7dg3i4axhfqlnj145l011x"; })
+  (fetchNuGet { pname = "runtime.any.System.Runtime.InteropServices"; version = "4.3.0"; sha256 = "0c3g3g3jmhlhw4klrc86ka9fjbl7i59ds1fadsb2l8nqf8z3kb19"; })
+  (fetchNuGet { pname = "runtime.any.System.Text.Encoding"; version = "4.3.0"; sha256 = "0aqqi1v4wx51h51mk956y783wzags13wa7mgqyclacmsmpv02ps3"; })
+  (fetchNuGet { pname = "runtime.any.System.Text.Encoding.Extensions"; version = "4.3.0"; sha256 = "0lqhgqi0i8194ryqq6v2gqx0fb86db2gqknbm0aq31wb378j7ip8"; })
+  (fetchNuGet { pname = "runtime.any.System.Threading.Tasks"; version = "4.3.0"; sha256 = "03mnvkhskbzxddz4hm113zsch1jyzh2cs450dk3rgfjp8crlw1va"; })
+  (fetchNuGet { pname = "runtime.any.System.Threading.Timer"; version = "4.3.0"; sha256 = "0aw4phrhwqz9m61r79vyfl5la64bjxj8l34qnrcwb28v49fg2086"; })
+  (fetchNuGet { pname = "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "16rnxzpk5dpbbl1x354yrlsbvwylrq456xzpsha1n9y3glnhyx9d"; })
+  (fetchNuGet { pname = "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0hkg03sgm2wyq8nqk6dbm9jh5vcq57ry42lkqdmfklrw89lsmr59"; })
+  (fetchNuGet { pname = "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0c2p354hjx58xhhz7wv6div8xpi90sc6ibdm40qin21bvi7ymcaa"; })
+  (fetchNuGet { pname = "runtime.native.System"; version = "4.0.0"; sha256 = "1ppk69xk59ggacj9n7g6fyxvzmk1g5p4fkijm0d7xqfkig98qrkf"; })
+  (fetchNuGet { pname = "runtime.native.System"; version = "4.3.0"; sha256 = "15hgf6zaq9b8br2wi1i3x0zvmk410nlmsmva9p0bbg73v6hml5k4"; })
+  (fetchNuGet { pname = "runtime.native.System.Data.SqlClient.sni"; version = "4.4.0"; sha256 = "15wnpyy506q3vyk1yzdjjf49zpdynr7ghh0x5fbz4pcc1if0p9ky"; })
+  (fetchNuGet { pname = "runtime.native.System.IO.Compression"; version = "4.1.0"; sha256 = "0d720z4lzyfcabmmnvh0bnj76ll7djhji2hmfh3h44sdkjnlkknk"; })
+  (fetchNuGet { pname = "runtime.native.System.IO.Compression"; version = "4.3.0"; sha256 = "1vvivbqsk6y4hzcid27pqpm5bsi6sc50hvqwbcx8aap5ifrxfs8d"; })
+  (fetchNuGet { pname = "runtime.native.System.Net.Http"; version = "4.0.1"; sha256 = "1hgv2bmbaskx77v8glh7waxws973jn4ah35zysnkxmf0196sfxg6"; })
+  (fetchNuGet { pname = "runtime.native.System.Net.Http"; version = "4.3.0"; sha256 = "1n6rgz5132lcibbch1qlf0g9jk60r0kqv087hxc0lisy50zpm7kk"; })
+  (fetchNuGet { pname = "runtime.native.System.Security.Cryptography"; version = "4.0.0"; sha256 = "0k57aa2c3b10wl3hfqbgrl7xq7g8hh3a3ir44b31dn5p61iiw3z9"; })
+  (fetchNuGet { pname = "runtime.native.System.Security.Cryptography.Apple"; version = "4.3.0"; sha256 = "1b61p6gw1m02cc1ry996fl49liiwky6181dzr873g9ds92zl326q"; })
+  (fetchNuGet { pname = "runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "18pzfdlwsg2nb1jjjjzyb5qlgy6xjxzmhnfaijq5s2jw3cm3ab97"; })
+  (fetchNuGet { pname = "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0qyynf9nz5i7pc26cwhgi8j62ps27sqmf78ijcfgzab50z9g8ay3"; })
+  (fetchNuGet { pname = "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "1klrs545awhayryma6l7g2pvnp9xy4z0r1i40r80zb45q3i9nbyf"; })
+  (fetchNuGet { pname = "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple"; version = "4.3.0"; sha256 = "10yc8jdrwgcl44b4g93f1ds76b176bajd3zqi2faf5rvh1vy9smi"; })
+  (fetchNuGet { pname = "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0zcxjv5pckplvkg0r6mw3asggm7aqzbdjimhvsasb0cgm59x09l3"; })
+  (fetchNuGet { pname = "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0vhynn79ih7hw7cwjazn87rm9z9fj0rvxgzlab36jybgcpcgphsn"; })
+  (fetchNuGet { pname = "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "160p68l2c7cqmyqjwxydcvgw7lvl1cr0znkw8fp24d1by9mqc8p3"; })
+  (fetchNuGet { pname = "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "15zrc8fgd8zx28hdghcj5f5i34wf3l6bq5177075m2bc2j34jrqy"; })
+  (fetchNuGet { pname = "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "1p4dgxax6p7rlgj4q73k73rslcnz4wdcv8q2flg1s8ygwcm58ld5"; })
+  (fetchNuGet { pname = "runtime.unix.Microsoft.Win32.Primitives"; version = "4.3.0"; sha256 = "0y61k9zbxhdi0glg154v30kkq7f8646nif8lnnxbvkjpakggd5id"; })
+  (fetchNuGet { pname = "runtime.unix.System.Console"; version = "4.3.0"; sha256 = "1pfpkvc6x2if8zbdzg9rnc5fx51yllprl8zkm5npni2k50lisy80"; })
+  (fetchNuGet { pname = "runtime.unix.System.Diagnostics.Debug"; version = "4.3.0"; sha256 = "1lps7fbnw34bnh3lm31gs5c0g0dh7548wfmb8zz62v0zqz71msj5"; })
+  (fetchNuGet { pname = "runtime.unix.System.IO.FileSystem"; version = "4.3.0"; sha256 = "14nbkhvs7sji5r1saj2x8daz82rnf9kx28d3v2qss34qbr32dzix"; })
+  (fetchNuGet { pname = "runtime.unix.System.Net.Primitives"; version = "4.3.0"; sha256 = "0bdnglg59pzx9394sy4ic66kmxhqp8q8bvmykdxcbs5mm0ipwwm4"; })
+  (fetchNuGet { pname = "runtime.unix.System.Net.Sockets"; version = "4.3.0"; sha256 = "03npdxzy8gfv035bv1b9rz7c7hv0rxl5904wjz51if491mw0xy12"; })
+  (fetchNuGet { pname = "runtime.unix.System.Private.Uri"; version = "4.3.0"; sha256 = "1jx02q6kiwlvfksq1q9qr17fj78y5v6mwsszav4qcz9z25d5g6vk"; })
+  (fetchNuGet { pname = "runtime.unix.System.Runtime.Extensions"; version = "4.3.0"; sha256 = "0pnxxmm8whx38dp6yvwgmh22smknxmqs5n513fc7m4wxvs1bvi4p"; })
+  (fetchNuGet { pname = "runtime.win-arm64.runtime.native.System.Data.SqlClient.sni"; version = "4.4.0"; sha256 = "07byf1iyqb7jkb17sp0mmjk46fwq6fx8mlpzywxl7qk09sma44gk"; })
+  (fetchNuGet { pname = "runtime.win-x64.runtime.native.System.Data.SqlClient.sni"; version = "4.4.0"; sha256 = "0167s4mpq8bzk3y11pylnynzjr2nc84w96al9x4l8yrf34ccm18y"; })
+  (fetchNuGet { pname = "runtime.win-x86.runtime.native.System.Data.SqlClient.sni"; version = "4.4.0"; sha256 = "0k3rkfrlm9jjz56dra61jgxinb8zsqlqzik2sjwz7f8v6z6ddycc"; })
+  (fetchNuGet { pname = "Scrutor"; version = "3.3.0"; sha256 = "0qdfbp73hbsiqbv0rg6f91hnp1j535iqk8bmp3ickwd7w337m1vi"; })
+  (fetchNuGet { pname = "Serilog"; version = "2.12.0"; sha256 = "0lqxpc96qcjkv9pr1rln7mi4y7n7jdi4vb36c2fv3845w1vswgr4"; })
+  (fetchNuGet { pname = "Serilog.AspNetCore"; version = "6.0.1"; sha256 = "1i3cs0dfba82x4m08i0h3wv53dnbx3j3lidsqd6flgfhk5y8q13q"; })
+  (fetchNuGet { pname = "Serilog.Enrichers.Thread"; version = "3.2.0-dev-00752"; sha256 = "0d0phxzdpc8xkbyd18s1dcv9xa22gqs2i2x5cpa9qzj0g8zwp641"; })
+  (fetchNuGet { pname = "Serilog.Extensions.Hosting"; version = "5.0.1"; sha256 = "11fs8qiikv3flpl6yhfrwflgvbdy62np7blx7nzcf6gx02zdgy1b"; })
+  (fetchNuGet { pname = "Serilog.Extensions.Logging"; version = "3.0.1"; sha256 = "069qy7dm5nxb372ij112ppa6m99b4iaimj3sji74m659fwrcrl9a"; })
+  (fetchNuGet { pname = "Serilog.Extensions.Logging"; version = "3.1.0"; sha256 = "0lv370ks2fjdn1nsgkbzbmw6hybnincw3jabr471a5w39pp4fl1c"; })
+  (fetchNuGet { pname = "Serilog.Formatting.Compact"; version = "1.1.0"; sha256 = "1w3qhj1jrihb20gr9la4r4gcmdyyy6dai2xflwhzvgqrq05wlycy"; })
+  (fetchNuGet { pname = "Serilog.Settings.Configuration"; version = "3.4.0"; sha256 = "1l6fyy9y5a168i1mm107aqyrwzhqmpy0cp1v13l2b89yv8dc105j"; })
+  (fetchNuGet { pname = "Serilog.Sinks.AspNetCore.SignalR"; version = "0.4.0"; sha256 = "0sljv39dr8mfbxjzqzik6qa72rc48v9z1hny4j61381cscnank1a"; })
+  (fetchNuGet { pname = "Serilog.Sinks.Console"; version = "4.1.0"; sha256 = "1rpkphmqfh3bv3m7v1zwz88wz4sirj4xqyff9ga0c6bqhblj6wii"; })
+  (fetchNuGet { pname = "Serilog.Sinks.Debug"; version = "2.0.0"; sha256 = "1i7j870l47gan3gpnnlzkccn5lbm7518cnkp25a3g5gp9l0dbwpw"; })
+  (fetchNuGet { pname = "Serilog.Sinks.File"; version = "5.0.0"; sha256 = "097rngmgcrdfy7jy8j7dq3xaq2qky8ijwg0ws6bfv5lx0f3vvb0q"; })
+  (fetchNuGet { pname = "Serilog.Sinks.SignalR.Core"; version = "0.1.2"; sha256 = "16f86661vr7gw8xay1735y551p0z39mks7xagwxb8lxqxwmm4gzf"; })
+  (fetchNuGet { pname = "SharpCompress"; version = "0.32.2"; sha256 = "1p198bl08ia89rf4n6yjpacj3yrz6s574snsfl40l8vlqcdrc1pm"; })
+  (fetchNuGet { pname = "SixLabors.ImageSharp"; version = "2.1.3"; sha256 = "12qb0r7v2v91vw8q8ygr67y527gwhbas6d6zdvrv4ksxwjx9dzp9"; })
+  (fetchNuGet { pname = "SonarAnalyzer.CSharp"; version = "8.47.0.55603"; sha256 = "1rwrhag17zdwf96mw1c2cc0xk555w310c7gadlc4gqgaim0c2xdp"; })
+  (fetchNuGet { pname = "sqlite-net-pcl"; version = "1.7.335"; sha256 = "1wlgr2s7gij7pgm9f9vrb1mkiniwm2mqxzxqdkixc81n3d27q1qn"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.bundle_e_sqlite3"; version = "2.0.6"; sha256 = "1ip0a653dx5cqybxg27zyz5ps31f2yz50g3jvz3vx39isx79gax3"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.bundle_green"; version = "2.0.3"; sha256 = "1rhzih4i82mnxac0bhcjp657g8fx83b95n39lkfkyqjbf591jc3k"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.core"; version = "2.0.3"; sha256 = "0m7k63zbyplgydn27yhy79hwjg869ar90ygkzc64l537wkn93ri3"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.core"; version = "2.0.6"; sha256 = "1w4iyg0v1v1z2m7akq7rv8lsgixp2m08732vr14vgpqs918bsy1i"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.lib.e_sqlite3"; version = "2.0.3"; sha256 = "0s0v2da7jim23wkkdasww8zmjqr9v3w082mfii8nybmkr9x4zz6x"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.lib.e_sqlite3"; version = "2.0.6"; sha256 = "16378rh1lcqxynf5qj0kh8mrsb0jp37qqwg4285kqc5pknvh1bx3"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.provider.dynamic_cdecl"; version = "2.0.3"; sha256 = "14mrvriw05hqzplfwz98082n5jqizix500hdl3vkvkjg9qvprhpy"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.provider.e_sqlite3"; version = "2.0.6"; sha256 = "0chgrqyycb1kqnaxnhhfg0850b94blhzni8zn79c7ggb3pd2ykyz"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore"; version = "6.4.0"; sha256 = "1jkgjnkjcb6dif0lzn7whjwwdd4fi6mzkmkdx8sfmv5cffzq4fvk"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore.Filters"; version = "7.0.6"; sha256 = "1wqm77sszmw7g5g8rmij5gw76ppr2j6zal24w4dhnf0wk8hqa8m6"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore.Filters.Abstractions"; version = "7.0.6"; sha256 = "0fd3f2m1hf01r3z2ag4x0mc3imc4psnnqds4pca2q8lhmmfpnrgx"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore.Swagger"; version = "5.0.0"; sha256 = "1341nv8nmh6avs3y7w2szzir5qd0bndxwrkdmvvj3hcxj1126w2f"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore.Swagger"; version = "6.4.0"; sha256 = "1wccx8ig2xc6xcfh774m5z34w6jn0hjffiwc5sq9yl63zkv01vnn"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore.SwaggerGen"; version = "5.0.0"; sha256 = "00swg2avqnb38q2bsxljd34n8rpknp74h9vbn0fdnfds3a32cqr4"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore.SwaggerGen"; version = "6.4.0"; sha256 = "1k58j6lfqcgrl5f7dw0xnbq6w5bvr42a9fc44vwbzl52kzjdlnh2"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore.SwaggerUI"; version = "6.4.0"; sha256 = "1rxgf0hbkkzywh8z7asky2rrh1gpnrr514v1aj5vnmh49sa31kiz"; })
+  (fetchNuGet { pname = "System.AppContext"; version = "4.1.0"; sha256 = "0fv3cma1jp4vgj7a8hqc9n7hr1f1kjp541s6z0q1r6nazb4iz9mz"; })
+  (fetchNuGet { pname = "System.AppContext"; version = "4.3.0"; sha256 = "1649qvy3dar900z3g817h17nl8jp4ka5vcfmsr05kh0fshn7j3ya"; })
+  (fetchNuGet { pname = "System.Buffers"; version = "4.0.0"; sha256 = "13s659bcmg9nwb6z78971z1lr6bmh2wghxi1ayqyzl4jijd351gr"; })
+  (fetchNuGet { pname = "System.Buffers"; version = "4.3.0"; sha256 = "0fgns20ispwrfqll4q1zc1waqcmylb3zc50ys9x8zlwxh9pmd9jy"; })
+  (fetchNuGet { pname = "System.Buffers"; version = "4.5.0"; sha256 = "1ywfqn4md6g3iilpxjn5dsr0f5lx6z0yvhqp4pgjcamygg73cz2c"; })
+  (fetchNuGet { pname = "System.Buffers"; version = "4.5.1"; sha256 = "04kb1mdrlcixj9zh1xdi5as0k0qi8byr5mi3p3jcxx72qz93s2y3"; })
+  (fetchNuGet { pname = "System.Collections"; version = "4.0.11"; sha256 = "1ga40f5lrwldiyw6vy67d0sg7jd7ww6kgwbksm19wrvq9hr0bsm6"; })
+  (fetchNuGet { pname = "System.Collections"; version = "4.3.0"; sha256 = "19r4y64dqyrq6k4706dnyhhw7fs24kpp3awak7whzss39dakpxk9"; })
+  (fetchNuGet { pname = "System.Collections.Concurrent"; version = "4.0.12"; sha256 = "07y08kvrzpak873pmyxs129g1ch8l27zmg51pcyj2jvq03n0r0fc"; })
+  (fetchNuGet { pname = "System.Collections.Concurrent"; version = "4.3.0"; sha256 = "0wi10md9aq33jrkh2c24wr2n9hrpyamsdhsxdcnf43b7y86kkii8"; })
+  (fetchNuGet { pname = "System.Collections.Immutable"; version = "6.0.0"; sha256 = "1js98kmjn47ivcvkjqdmyipzknb9xbndssczm8gq224pbaj1p88c"; })
+  (fetchNuGet { pname = "System.ComponentModel.Annotations"; version = "4.5.0"; sha256 = "1jj6f6g87k0iwsgmg3xmnn67a14mq88np0l1ys5zkxhkvbc8976p"; })
+  (fetchNuGet { pname = "System.Console"; version = "4.0.0"; sha256 = "0ynxqbc3z1nwbrc11hkkpw9skw116z4y9wjzn7id49p9yi7mzmlf"; })
+  (fetchNuGet { pname = "System.Console"; version = "4.3.0"; sha256 = "1flr7a9x920mr5cjsqmsy9wgnv3lvd0h1g521pdr1lkb2qycy7ay"; })
+  (fetchNuGet { pname = "System.Data.SqlClient"; version = "4.4.0"; sha256 = "1djh6i8s9s035glf2kg3fnlxkj36gf6327w5q44229nw48y6x8kh"; })
+  (fetchNuGet { pname = "System.Diagnostics.Debug"; version = "4.0.11"; sha256 = "0gmjghrqmlgzxivd2xl50ncbglb7ljzb66rlx8ws6dv8jm0d5siz"; })
+  (fetchNuGet { pname = "System.Diagnostics.Debug"; version = "4.3.0"; sha256 = "00yjlf19wjydyr6cfviaph3vsjzg3d5nvnya26i2fvfg53sknh3y"; })
+  (fetchNuGet { pname = "System.Diagnostics.DiagnosticSource"; version = "4.0.0"; sha256 = "1n6c3fbz7v8d3pn77h4v5wvsfrfg7v1c57lg3nff3cjyh597v23m"; })
+  (fetchNuGet { pname = "System.Diagnostics.DiagnosticSource"; version = "4.3.0"; sha256 = "0z6m3pbiy0qw6rn3n209rrzf9x1k4002zh90vwcrsym09ipm2liq"; })
+  (fetchNuGet { pname = "System.Diagnostics.DiagnosticSource"; version = "6.0.0"; sha256 = "0rrihs9lnb1h6x4h0hn6kgfnh58qq7hx8qq99gh6fayx4dcnx3s5"; })
+  (fetchNuGet { pname = "System.Diagnostics.EventLog"; version = "6.0.0"; sha256 = "08y1x2d5w2hnhkh9r1998pjc7r4qp0rmzax062abha85s11chifd"; })
+  (fetchNuGet { pname = "System.Diagnostics.Tools"; version = "4.0.1"; sha256 = "19cknvg07yhakcvpxg3cxa0bwadplin6kyxd8mpjjpwnp56nl85x"; })
+  (fetchNuGet { pname = "System.Diagnostics.Tools"; version = "4.3.0"; sha256 = "0in3pic3s2ddyibi8cvgl102zmvp9r9mchh82ns9f0ms4basylw1"; })
+  (fetchNuGet { pname = "System.Diagnostics.Tracing"; version = "4.1.0"; sha256 = "1d2r76v1x610x61ahfpigda89gd13qydz6vbwzhpqlyvq8jj6394"; })
+  (fetchNuGet { pname = "System.Diagnostics.Tracing"; version = "4.3.0"; sha256 = "1m3bx6c2s958qligl67q7grkwfz3w53hpy7nc97mh6f7j5k168c4"; })
+  (fetchNuGet { pname = "System.Drawing.Common"; version = "6.0.0"; sha256 = "02n8rzm58dac2np8b3xw8ychbvylja4nh6938l5k2fhyn40imlgz"; })
+  (fetchNuGet { pname = "System.Dynamic.Runtime"; version = "4.0.11"; sha256 = "1pla2dx8gkidf7xkciig6nifdsb494axjvzvann8g2lp3dbqasm9"; })
+  (fetchNuGet { pname = "System.Globalization"; version = "4.0.11"; sha256 = "070c5jbas2v7smm660zaf1gh0489xanjqymkvafcs4f8cdrs1d5d"; })
+  (fetchNuGet { pname = "System.Globalization"; version = "4.3.0"; sha256 = "1cp68vv683n6ic2zqh2s1fn4c2sd87g5hpp6l4d4nj4536jz98ki"; })
+  (fetchNuGet { pname = "System.Globalization.Calendars"; version = "4.0.1"; sha256 = "0bv0alrm2ck2zk3rz25lfyk9h42f3ywq77mx1syl6vvyncnpg4qh"; })
+  (fetchNuGet { pname = "System.Globalization.Calendars"; version = "4.3.0"; sha256 = "1xwl230bkakzzkrggy1l1lxmm3xlhk4bq2pkv790j5lm8g887lxq"; })
+  (fetchNuGet { pname = "System.Globalization.Extensions"; version = "4.0.1"; sha256 = "0hjhdb5ri8z9l93bw04s7ynwrjrhx2n0p34sf33a9hl9phz69fyc"; })
+  (fetchNuGet { pname = "System.Globalization.Extensions"; version = "4.3.0"; sha256 = "02a5zfxavhv3jd437bsncbhd2fp1zv4gxzakp1an9l6kdq1mcqls"; })
+  (fetchNuGet { pname = "System.IdentityModel.Tokens.Jwt"; version = "6.24.0"; sha256 = "1s6r8ivhbnv1hdybizmw0336z0dsv4dis3p2d658hzsv5p758yip"; })
+  (fetchNuGet { pname = "System.IO"; version = "4.1.0"; sha256 = "1g0yb8p11vfd0kbkyzlfsbsp5z44lwsvyc0h3dpw6vqnbi035ajp"; })
+  (fetchNuGet { pname = "System.IO"; version = "4.3.0"; sha256 = "05l9qdrzhm4s5dixmx68kxwif4l99ll5gqmh7rqgw554fx0agv5f"; })
+  (fetchNuGet { pname = "System.IO.Abstractions"; version = "17.2.3"; sha256 = "1fs3asbc3f5maxc5il2iqmhhlbz4c69lh8r0r0xwjcjbly7agn0l"; })
+  (fetchNuGet { pname = "System.IO.Compression"; version = "4.1.0"; sha256 = "0iym7s3jkl8n0vzm3jd6xqg9zjjjqni05x45dwxyjr2dy88hlgji"; })
+  (fetchNuGet { pname = "System.IO.Compression"; version = "4.3.0"; sha256 = "084zc82yi6yllgda0zkgl2ys48sypiswbiwrv7irb3r0ai1fp4vz"; })
+  (fetchNuGet { pname = "System.IO.Compression.ZipFile"; version = "4.0.1"; sha256 = "0h72znbagmgvswzr46mihn7xm7chfk2fhrp5krzkjf29pz0i6z82"; })
+  (fetchNuGet { pname = "System.IO.Compression.ZipFile"; version = "4.3.0"; sha256 = "1yxy5pq4dnsm9hlkg9ysh5f6bf3fahqqb6p8668ndy5c0lk7w2ar"; })
+  (fetchNuGet { pname = "System.IO.FileSystem"; version = "4.0.1"; sha256 = "0kgfpw6w4djqra3w5crrg8xivbanh1w9dh3qapb28q060wb9flp1"; })
+  (fetchNuGet { pname = "System.IO.FileSystem"; version = "4.3.0"; sha256 = "0z2dfrbra9i6y16mm9v1v6k47f0fm617vlb7s5iybjjsz6g1ilmw"; })
+  (fetchNuGet { pname = "System.IO.FileSystem.Primitives"; version = "4.0.1"; sha256 = "1s0mniajj3lvbyf7vfb5shp4ink5yibsx945k6lvxa96r8la1612"; })
+  (fetchNuGet { pname = "System.IO.FileSystem.Primitives"; version = "4.3.0"; sha256 = "0j6ndgglcf4brg2lz4wzsh1av1gh8xrzdsn9f0yznskhqn1xzj9c"; })
+  (fetchNuGet { pname = "System.IO.Pipelines"; version = "4.5.2"; sha256 = "045sn3vyk5xysjjm19q4dj5c1g1rf8l98n4qsl9pl9id4fn08yq1"; })
+  (fetchNuGet { pname = "System.Linq"; version = "4.1.0"; sha256 = "1ppg83svb39hj4hpp5k7kcryzrf3sfnm08vxd5sm2drrijsla2k5"; })
+  (fetchNuGet { pname = "System.Linq"; version = "4.3.0"; sha256 = "1w0gmba695rbr80l1k2h4mrwzbzsyfl2z4klmpbsvsg5pm4a56s7"; })
+  (fetchNuGet { pname = "System.Linq.Expressions"; version = "4.1.0"; sha256 = "1gpdxl6ip06cnab7n3zlcg6mqp7kknf73s8wjinzi4p0apw82fpg"; })
+  (fetchNuGet { pname = "System.Linq.Expressions"; version = "4.3.0"; sha256 = "0ky2nrcvh70rqq88m9a5yqabsl4fyd17bpr63iy2mbivjs2nyypv"; })
+  (fetchNuGet { pname = "System.Memory"; version = "4.5.1"; sha256 = "0f07d7hny38lq9w69wx4lxkn4wszrqf9m9js6fh9is645csm167c"; })
+  (fetchNuGet { pname = "System.Memory"; version = "4.5.3"; sha256 = "0naqahm3wljxb5a911d37mwjqjdxv9l0b49p5dmfyijvni2ppy8a"; })
+  (fetchNuGet { pname = "System.Memory"; version = "4.5.4"; sha256 = "14gbbs22mcxwggn0fcfs1b062521azb9fbb7c113x0mq6dzq9h6y"; })
+  (fetchNuGet { pname = "System.Net.Http"; version = "4.1.0"; sha256 = "1i5rqij1icg05j8rrkw4gd4pgia1978mqhjzhsjg69lvwcdfg8yb"; })
+  (fetchNuGet { pname = "System.Net.Http"; version = "4.3.0"; sha256 = "1i4gc757xqrzflbk7kc5ksn20kwwfjhw9w7pgdkn19y3cgnl302j"; })
+  (fetchNuGet { pname = "System.Net.NameResolution"; version = "4.3.0"; sha256 = "15r75pwc0rm3vvwsn8rvm2krf929mjfwliv0mpicjnii24470rkq"; })
+  (fetchNuGet { pname = "System.Net.Primitives"; version = "4.0.11"; sha256 = "10xzzaynkzkakp7jai1ik3r805zrqjxiz7vcagchyxs2v26a516r"; })
+  (fetchNuGet { pname = "System.Net.Primitives"; version = "4.3.0"; sha256 = "0c87k50rmdgmxx7df2khd9qj7q35j9rzdmm2572cc55dygmdk3ii"; })
+  (fetchNuGet { pname = "System.Net.Sockets"; version = "4.1.0"; sha256 = "1385fvh8h29da5hh58jm1v78fzi9fi5vj93vhlm2kvqpfahvpqls"; })
+  (fetchNuGet { pname = "System.Net.Sockets"; version = "4.3.0"; sha256 = "1ssa65k6chcgi6mfmzrznvqaxk8jp0gvl77xhf1hbzakjnpxspla"; })
+  (fetchNuGet { pname = "System.Net.WebSockets.WebSocketProtocol"; version = "4.5.1"; sha256 = "1n0ag9ws6fgyqcz39xyk5dnchskfji8bcgqw90i2ai7lyvd843p6"; })
+  (fetchNuGet { pname = "System.ObjectModel"; version = "4.0.12"; sha256 = "1sybkfi60a4588xn34nd9a58png36i0xr4y4v4kqpg8wlvy5krrj"; })
+  (fetchNuGet { pname = "System.ObjectModel"; version = "4.3.0"; sha256 = "191p63zy5rpqx7dnrb3h7prvgixmk168fhvvkkvhlazncf8r3nc2"; })
+  (fetchNuGet { pname = "System.Private.Uri"; version = "4.3.0"; sha256 = "04r1lkdnsznin0fj4ya1zikxiqr0h6r6a1ww2dsm60gqhdrf0mvx"; })
+  (fetchNuGet { pname = "System.Reflection"; version = "4.1.0"; sha256 = "1js89429pfw79mxvbzp8p3q93il6rdff332hddhzi5wqglc4gml9"; })
+  (fetchNuGet { pname = "System.Reflection"; version = "4.3.0"; sha256 = "0xl55k0mw8cd8ra6dxzh974nxif58s3k1rjv1vbd7gjbjr39j11m"; })
+  (fetchNuGet { pname = "System.Reflection.Emit"; version = "4.0.1"; sha256 = "0ydqcsvh6smi41gyaakglnv252625hf29f7kywy2c70nhii2ylqp"; })
+  (fetchNuGet { pname = "System.Reflection.Emit"; version = "4.3.0"; sha256 = "11f8y3qfysfcrscjpjym9msk7lsfxkk4fmz9qq95kn3jd0769f74"; })
+  (fetchNuGet { pname = "System.Reflection.Emit.ILGeneration"; version = "4.0.1"; sha256 = "1pcd2ig6bg144y10w7yxgc9d22r7c7ww7qn1frdfwgxr24j9wvv0"; })
+  (fetchNuGet { pname = "System.Reflection.Emit.ILGeneration"; version = "4.3.0"; sha256 = "0w1n67glpv8241vnpz1kl14sy7zlnw414aqwj4hcx5nd86f6994q"; })
+  (fetchNuGet { pname = "System.Reflection.Emit.Lightweight"; version = "4.0.1"; sha256 = "1s4b043zdbx9k39lfhvsk68msv1nxbidhkq6nbm27q7sf8xcsnxr"; })
+  (fetchNuGet { pname = "System.Reflection.Emit.Lightweight"; version = "4.3.0"; sha256 = "0ql7lcakycrvzgi9kxz1b3lljd990az1x6c4jsiwcacrvimpib5c"; })
+  (fetchNuGet { pname = "System.Reflection.Extensions"; version = "4.0.1"; sha256 = "0m7wqwq0zqq9gbpiqvgk3sr92cbrw7cp3xn53xvw7zj6rz6fdirn"; })
+  (fetchNuGet { pname = "System.Reflection.Extensions"; version = "4.3.0"; sha256 = "02bly8bdc98gs22lqsfx9xicblszr2yan7v2mmw3g7hy6miq5hwq"; })
+  (fetchNuGet { pname = "System.Reflection.Primitives"; version = "4.0.1"; sha256 = "1bangaabhsl4k9fg8khn83wm6yial8ik1sza7401621jc6jrym28"; })
+  (fetchNuGet { pname = "System.Reflection.Primitives"; version = "4.3.0"; sha256 = "04xqa33bld78yv5r93a8n76shvc8wwcdgr1qvvjh959g3rc31276"; })
+  (fetchNuGet { pname = "System.Reflection.TypeExtensions"; version = "4.1.0"; sha256 = "1bjli8a7sc7jlxqgcagl9nh8axzfl11f4ld3rjqsyxc516iijij7"; })
+  (fetchNuGet { pname = "System.Reflection.TypeExtensions"; version = "4.3.0"; sha256 = "0y2ssg08d817p0vdag98vn238gyrrynjdj4181hdg780sif3ykp1"; })
+  (fetchNuGet { pname = "System.Resources.ResourceManager"; version = "4.0.1"; sha256 = "0b4i7mncaf8cnai85jv3wnw6hps140cxz8vylv2bik6wyzgvz7bi"; })
+  (fetchNuGet { pname = "System.Resources.ResourceManager"; version = "4.3.0"; sha256 = "0sjqlzsryb0mg4y4xzf35xi523s4is4hz9q4qgdvlvgivl7qxn49"; })
+  (fetchNuGet { pname = "System.Runtime"; version = "4.1.0"; sha256 = "02hdkgk13rvsd6r9yafbwzss8kr55wnj8d5c7xjnp8gqrwc8sn0m"; })
+  (fetchNuGet { pname = "System.Runtime"; version = "4.3.0"; sha256 = "066ixvgbf2c929kgknshcxqj6539ax7b9m570cp8n179cpfkapz7"; })
+  (fetchNuGet { pname = "System.Runtime.CompilerServices.Unsafe"; version = "4.4.0"; sha256 = "0a6ahgi5b148sl5qyfpyw383p3cb4yrkm802k29fsi4mxkiwir29"; })
+  (fetchNuGet { pname = "System.Runtime.CompilerServices.Unsafe"; version = "4.5.1"; sha256 = "1xcrjx5fwg284qdnxyi2d0lzdm5q4frlpkp0nf6vvkx1kdz2prrf"; })
+  (fetchNuGet { pname = "System.Runtime.CompilerServices.Unsafe"; version = "4.5.2"; sha256 = "1vz4275fjij8inf31np78hw50al8nqkngk04p3xv5n4fcmf1grgi"; })
+  (fetchNuGet { pname = "System.Runtime.CompilerServices.Unsafe"; version = "5.0.0"; sha256 = "02k25ivn50dmqx5jn8hawwmz24yf0454fjd823qk6lygj9513q4x"; })
+  (fetchNuGet { pname = "System.Runtime.CompilerServices.Unsafe"; version = "6.0.0"; sha256 = "0qm741kh4rh57wky16sq4m0v05fxmkjjr87krycf5vp9f0zbahbc"; })
+  (fetchNuGet { pname = "System.Runtime.Extensions"; version = "4.1.0"; sha256 = "0rw4rm4vsm3h3szxp9iijc3ksyviwsv6f63dng3vhqyg4vjdkc2z"; })
+  (fetchNuGet { pname = "System.Runtime.Extensions"; version = "4.3.0"; sha256 = "1ykp3dnhwvm48nap8q23893hagf665k0kn3cbgsqpwzbijdcgc60"; })
+  (fetchNuGet { pname = "System.Runtime.Handles"; version = "4.0.1"; sha256 = "1g0zrdi5508v49pfm3iii2hn6nm00bgvfpjq1zxknfjrxxa20r4g"; })
+  (fetchNuGet { pname = "System.Runtime.Handles"; version = "4.3.0"; sha256 = "0sw2gfj2xr7sw9qjn0j3l9yw07x73lcs97p8xfc9w1x9h5g5m7i8"; })
+  (fetchNuGet { pname = "System.Runtime.InteropServices"; version = "4.1.0"; sha256 = "01kxqppx3dr3b6b286xafqilv4s2n0gqvfgzfd4z943ga9i81is1"; })
+  (fetchNuGet { pname = "System.Runtime.InteropServices"; version = "4.3.0"; sha256 = "00hywrn4g7hva1b2qri2s6rabzwgxnbpw9zfxmz28z09cpwwgh7j"; })
+  (fetchNuGet { pname = "System.Runtime.InteropServices.RuntimeInformation"; version = "4.0.0"; sha256 = "0glmvarf3jz5xh22iy3w9v3wyragcm4hfdr17v90vs7vcrm7fgp6"; })
+  (fetchNuGet { pname = "System.Runtime.InteropServices.RuntimeInformation"; version = "4.3.0"; sha256 = "0q18r1sh4vn7bvqgd6dmqlw5v28flbpj349mkdish2vjyvmnb2ii"; })
+  (fetchNuGet { pname = "System.Runtime.Numerics"; version = "4.0.1"; sha256 = "1y308zfvy0l5nrn46mqqr4wb4z1xk758pkk8svbz8b5ij7jnv4nn"; })
+  (fetchNuGet { pname = "System.Runtime.Numerics"; version = "4.3.0"; sha256 = "19rav39sr5dky7afygh309qamqqmi9kcwvz3i0c5700v0c5cg61z"; })
+  (fetchNuGet { pname = "System.Runtime.Serialization.Primitives"; version = "4.1.1"; sha256 = "042rfjixknlr6r10vx2pgf56yming8lkjikamg3g4v29ikk78h7k"; })
+  (fetchNuGet { pname = "System.Security.AccessControl"; version = "4.4.0"; sha256 = "0ixqw47krkazsw0ycm22ivkv7dpg6cjz8z8g0ii44bsx4l8gcx17"; })
+  (fetchNuGet { pname = "System.Security.Claims"; version = "4.3.0"; sha256 = "0jvfn7j22l3mm28qjy3rcw287y9h65ha4m940waaxah07jnbzrhn"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Algorithms"; version = "4.2.0"; sha256 = "148s9g5dgm33ri7dnh19s4lgnlxbpwvrw2jnzllq2kijj4i4vs85"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Algorithms"; version = "4.3.0"; sha256 = "03sq183pfl5kp7gkvq77myv7kbpdnq3y0xj7vi4q1kaw54sny0ml"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Cng"; version = "4.2.0"; sha256 = "118jijz446kix20blxip0f0q8mhsh9bz118mwc2ch1p6g7facpzc"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Cng"; version = "4.3.0"; sha256 = "1k468aswafdgf56ab6yrn7649kfqx2wm9aslywjam1hdmk5yypmv"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Cng"; version = "4.5.0"; sha256 = "1pm4ykbcz48f1hdmwpia432ha6qbb9kbrxrrp7cg3m8q8xn52ngn"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Csp"; version = "4.0.0"; sha256 = "1cwv8lqj8r15q81d2pz2jwzzbaji0l28xfrpw29kdpsaypm92z2q"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Csp"; version = "4.3.0"; sha256 = "1x5wcrddf2s3hb8j78cry7yalca4lb5vfnkrysagbn6r9x6xvrx1"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Encoding"; version = "4.0.0"; sha256 = "0a8y1a5wkmpawc787gfmnrnbzdgxmx1a14ax43jf3rj9gxmy3vk4"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Encoding"; version = "4.3.0"; sha256 = "1jr6w70igqn07k5zs1ph6xja97hxnb3mqbspdrff6cvssgrixs32"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.OpenSsl"; version = "4.0.0"; sha256 = "16sx3cig3d0ilvzl8xxgffmxbiqx87zdi8fc73i3i7zjih1a7f4q"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0givpvvj8yc7gv4lhb6s1prq6p2c4147204a0wib89inqzd87gqc"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Primitives"; version = "4.0.0"; sha256 = "0i7cfnwph9a10bm26m538h5xcr8b36jscp9sy1zhgifksxz4yixh"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Primitives"; version = "4.3.0"; sha256 = "0pyzncsv48zwly3lw4f2dayqswcfvdwq2nz0dgwmi7fj3pn64wby"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.X509Certificates"; version = "4.1.0"; sha256 = "0clg1bv55mfv5dq00m19cp634zx6inm31kf8ppbq1jgyjf2185dh"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.X509Certificates"; version = "4.3.0"; sha256 = "0valjcz5wksbvijylxijjxb1mp38mdhv03r533vnx1q3ikzdav9h"; })
+  (fetchNuGet { pname = "System.Security.Principal"; version = "4.3.0"; sha256 = "12cm2zws06z4lfc4dn31iqv7072zyi4m910d4r6wm8yx85arsfxf"; })
+  (fetchNuGet { pname = "System.Security.Principal.Windows"; version = "4.3.0"; sha256 = "00a0a7c40i3v4cb20s2cmh9csb5jv2l0frvnlzyfxh848xalpdwr"; })
+  (fetchNuGet { pname = "System.Security.Principal.Windows"; version = "4.4.0"; sha256 = "11rr16fp68apc0arsymgj18w8ajs9a4366wgx9iqwny4glrl20wp"; })
+  (fetchNuGet { pname = "System.Security.Principal.Windows"; version = "4.5.0"; sha256 = "0rmj89wsl5yzwh0kqjgx45vzf694v9p92r4x4q6yxldk1cv1hi86"; })
+  (fetchNuGet { pname = "System.Text.Encoding"; version = "4.0.11"; sha256 = "1dyqv0hijg265dwxg6l7aiv74102d6xjiwplh2ar1ly6xfaa4iiw"; })
+  (fetchNuGet { pname = "System.Text.Encoding"; version = "4.3.0"; sha256 = "1f04lkir4iladpp51sdgmis9dj4y8v08cka0mbmsy0frc9a4gjqr"; })
+  (fetchNuGet { pname = "System.Text.Encoding.CodePages"; version = "4.4.0"; sha256 = "07bzjnflxjk9vgpljfybrpqmvsr9qr2f20nq5wf11imwa5pbhgfc"; })
+  (fetchNuGet { pname = "System.Text.Encoding.CodePages"; version = "4.5.1"; sha256 = "1z21qyfs6sg76rp68qdx0c9iy57naan89pg7p6i3qpj8kyzn921w"; })
+  (fetchNuGet { pname = "System.Text.Encoding.CodePages"; version = "5.0.0"; sha256 = "1bn2pzaaq4wx9ixirr8151vm5hynn3lmrljcgjx9yghmm4k677k0"; })
+  (fetchNuGet { pname = "System.Text.Encoding.Extensions"; version = "4.0.11"; sha256 = "08nsfrpiwsg9x5ml4xyl3zyvjfdi4mvbqf93kjdh11j4fwkznizs"; })
+  (fetchNuGet { pname = "System.Text.Encoding.Extensions"; version = "4.3.0"; sha256 = "11q1y8hh5hrp5a3kw25cb6l00v5l5dvirkz8jr3sq00h1xgcgrxy"; })
+  (fetchNuGet { pname = "System.Text.Encodings.Web"; version = "4.5.0"; sha256 = "0srd5bva52n92i90wd88pzrqjsxnfgka3ilybwh7s6sf469y5s53"; })
+  (fetchNuGet { pname = "System.Text.Encodings.Web"; version = "6.0.0"; sha256 = "06n9ql3fmhpjl32g3492sj181zjml5dlcc5l76xq2h38c4f87sai"; })
+  (fetchNuGet { pname = "System.Text.Json"; version = "4.6.0"; sha256 = "0ism236hwi0k6axssfq58s1d8lihplwiz058pdvl8al71hagri39"; })
+  (fetchNuGet { pname = "System.Text.Json"; version = "4.7.2"; sha256 = "10xj1pw2dgd42anikvj9qm23ccssrcp7dpznpj4j7xjp1ikhy3y4"; })
+  (fetchNuGet { pname = "System.Text.Json"; version = "6.0.0"; sha256 = "1si2my1g0q0qv1hiqnji4xh9wd05qavxnzj9dwgs23iqvgjky0gl"; })
+  (fetchNuGet { pname = "System.Text.RegularExpressions"; version = "4.1.0"; sha256 = "1mw7vfkkyd04yn2fbhm38msk7dz2xwvib14ygjsb8dq2lcvr18y7"; })
+  (fetchNuGet { pname = "System.Text.RegularExpressions"; version = "4.3.0"; sha256 = "1bgq51k7fwld0njylfn7qc5fmwrk2137gdq7djqdsw347paa9c2l"; })
+  (fetchNuGet { pname = "System.Threading"; version = "4.0.11"; sha256 = "19x946h926bzvbsgj28csn46gak2crv2skpwsx80hbgazmkgb1ls"; })
+  (fetchNuGet { pname = "System.Threading"; version = "4.3.0"; sha256 = "0rw9wfamvhayp5zh3j7p1yfmx9b5khbf4q50d8k5rk993rskfd34"; })
+  (fetchNuGet { pname = "System.Threading.Channels"; version = "4.5.0"; sha256 = "0n6z3wjia7h2a5vl727p97riydnb6jhhkb1pdcnizza02dwkz0nz"; })
+  (fetchNuGet { pname = "System.Threading.Tasks"; version = "4.0.11"; sha256 = "0nr1r41rak82qfa5m0lhk9mp0k93bvfd7bbd9sdzwx9mb36g28p5"; })
+  (fetchNuGet { pname = "System.Threading.Tasks"; version = "4.3.0"; sha256 = "134z3v9abw3a6jsw17xl3f6hqjpak5l682k2vz39spj4kmydg6k7"; })
+  (fetchNuGet { pname = "System.Threading.Tasks.Extensions"; version = "4.0.0"; sha256 = "1cb51z062mvc2i8blpzmpn9d9mm4y307xrwi65di8ri18cz5r1zr"; })
+  (fetchNuGet { pname = "System.Threading.Tasks.Extensions"; version = "4.3.0"; sha256 = "1xxcx2xh8jin360yjwm4x4cf5y3a2bwpn2ygkfkwkicz7zk50s2z"; })
+  (fetchNuGet { pname = "System.Threading.Thread"; version = "4.0.0"; sha256 = "1gxxm5fl36pjjpnx1k688dcw8m9l7nmf802nxis6swdaw8k54jzc"; })
+  (fetchNuGet { pname = "System.Threading.ThreadPool"; version = "4.3.0"; sha256 = "027s1f4sbx0y1xqw2irqn6x161lzj8qwvnh2gn78ciiczdv10vf1"; })
+  (fetchNuGet { pname = "System.Threading.Timer"; version = "4.0.1"; sha256 = "15n54f1f8nn3mjcjrlzdg6q3520571y012mx7v991x2fvp73lmg6"; })
+  (fetchNuGet { pname = "System.Threading.Timer"; version = "4.3.0"; sha256 = "1nx773nsx6z5whv8kaa1wjh037id2f1cxhb69pvgv12hd2b6qs56"; })
+  (fetchNuGet { pname = "System.Xml.ReaderWriter"; version = "4.0.11"; sha256 = "0c6ky1jk5ada9m94wcadih98l6k1fvf6vi7vhn1msjixaha419l5"; })
+  (fetchNuGet { pname = "System.Xml.ReaderWriter"; version = "4.3.0"; sha256 = "0c47yllxifzmh8gq6rq6l36zzvw4kjvlszkqa9wq3fr59n0hl3s1"; })
+  (fetchNuGet { pname = "System.Xml.XDocument"; version = "4.0.11"; sha256 = "0n4lvpqzy9kc7qy1a4acwwd7b7pnvygv895az5640idl2y9zbz18"; })
+  (fetchNuGet { pname = "System.Xml.XDocument"; version = "4.3.0"; sha256 = "08h8fm4l77n0nd4i4fk2386y809bfbwqb7ih9d7564ifcxr5ssxd"; })
+  (fetchNuGet { pname = "VersOne.Epub"; version = "3.3.0-alpha1"; sha256 = "037wq88w6brfjswmraa1l6by7fcdd1nc3vri8plg9h6a7zjph4nc"; })
+]
diff --git a/nixpkgs/pkgs/servers/web-apps/lemmy/package.json b/nixpkgs/pkgs/servers/web-apps/lemmy/package.json
new file mode 100644
index 000000000000..97600d6801a2
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/lemmy/package.json
@@ -0,0 +1,149 @@
+{
+  "name": "lemmy-ui",
+  "description": "An isomorphic UI for lemmy",
+  "version": "0.19.3",
+  "author": "Dessalines <tyhou13@gmx.com>",
+  "license": "AGPL-3.0-only",
+  "scripts": {
+    "analyze": "webpack --mode=none",
+    "build:dev": "webpack --env COMMIT_HASH=$(git rev-parse --short HEAD) --mode=development",
+    "build:prod": "webpack --env COMMIT_HASH=$(git rev-parse --short HEAD) --mode=production",
+    "clean": "yarn run rimraf dist",
+    "dev": "yarn build:dev --watch",
+    "lint": "yarn translations:generate && tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx \"src/**\" && prettier --check \"src/**/*.{ts,tsx,js,css,scss}\"",
+    "postinstall": "husky install",
+    "prebuild:dev": "yarn clean && node generate_translations.js",
+    "prebuild:prod": "yarn clean && node generate_translations.js",
+    "prepare": "husky install",
+    "themes:build": "sass src/assets/css/themes/:src/assets/css/themes",
+    "themes:watch": "sass --watch src/assets/css/themes/:src/assets/css/themes",
+    "translations:generate": "node generate_translations.js",
+    "translations:init": "git submodule init && yarn translations:update",
+    "translations:update": "git submodule update --remote --recursive"
+  },
+  "repository": "https://github.com/LemmyNet/lemmy-ui",
+  "engines": {
+    "node": ">=8.9.0"
+  },
+  "dependencies": {
+    "@babel/plugin-proposal-class-properties": "^7.18.6",
+    "@babel/plugin-proposal-decorators": "^7.23.7",
+    "@babel/plugin-transform-runtime": "^7.23.7",
+    "@babel/plugin-transform-typescript": "^7.23.6",
+    "@babel/preset-env": "^7.23.8",
+    "@babel/preset-typescript": "^7.21.5",
+    "@babel/runtime": "^7.23.8",
+    "@emoji-mart/data": "^1.1.0",
+    "@shortcm/qr-image": "^9.0.2",
+    "autosize": "^6.0.1",
+    "babel-loader": "^9.1.3",
+    "babel-plugin-inferno": "^6.7.1",
+    "bootstrap": "^5.3.1",
+    "check-password-strength": "^2.0.7",
+    "classnames": "^2.5.1",
+    "clean-webpack-plugin": "^4.0.0",
+    "cookie": "^0.6.0",
+    "copy-webpack-plugin": "^12.0.2",
+    "css-loader": "^6.9.1",
+    "date-fns": "^3.2.0",
+    "emoji-mart": "^5.4.0",
+    "emoji-short-name": "^2.0.0",
+    "express": "~4.18.2",
+    "history": "^5.3.0",
+    "html-to-text": "^9.0.5",
+    "husky": "^8.0.3",
+    "i18next": "^23.7.16",
+    "inferno": "^8.2.3",
+    "inferno-create-element": "^8.2.3",
+    "inferno-helmet": "^5.2.1",
+    "inferno-hydrate": "^8.2.3",
+    "inferno-i18next-dess": "0.0.2",
+    "inferno-router": "^8.2.3",
+    "inferno-server": "^8.2.3",
+    "jwt-decode": "^4.0.0",
+    "lemmy-js-client": "0.19.2-alpha.1",
+    "lodash.isequal": "^4.5.0",
+    "markdown-it": "^14.0.0",
+    "markdown-it-bidi": "^0.1.0",
+    "markdown-it-container": "^4.0.0",
+    "markdown-it-emoji": "^3.0.0",
+    "markdown-it-footnote": "^4.0.0",
+    "markdown-it-highlightjs": "^4.0.1",
+    "markdown-it-html5-embed": "^1.0.0",
+    "markdown-it-ruby": "^0.1.1",
+    "markdown-it-sub": "^2.0.0",
+    "markdown-it-sup": "^2.0.0",
+    "mini-css-extract-plugin": "^2.7.7",
+    "register-service-worker": "^1.7.2",
+    "run-node-webpack-plugin": "^1.3.0",
+    "rxjs": "^7.8.1",
+    "sanitize-html": "^2.11.0",
+    "sass": "^1.70.0",
+    "sass-loader": "^14.0.0",
+    "serialize-javascript": "^6.0.2",
+    "service-worker-webpack": "^1.0.0",
+    "sharp": "0.32.6",
+    "tippy.js": "^6.3.7",
+    "toastify-js": "^1.12.0",
+    "tributejs": "^5.1.3",
+    "webpack": "^5.89.0",
+    "webpack-cli": "^5.1.4",
+    "webpack-node-externals": "^3.0.0"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.23.7",
+    "@types/autosize": "^4.0.0",
+    "@types/bootstrap": "^5.2.6",
+    "@types/cookie": "^0.6.0",
+    "@types/express": "^4.17.17",
+    "@types/html-to-text": "^9.0.0",
+    "@types/lodash.isequal": "^4.5.6",
+    "@types/markdown-it": "^13.0.7",
+    "@types/markdown-it-container": "^2.0.6",
+    "@types/node": "^20.11.5",
+    "@types/path-browserify": "^1.0.0",
+    "@types/sanitize-html": "^2.9.0",
+    "@types/serialize-javascript": "^5.0.1",
+    "@types/toastify-js": "^1.12.0",
+    "@typescript-eslint/eslint-plugin": "^6.19.0",
+    "@typescript-eslint/parser": "^6.19.0",
+    "eslint": "^8.56.0",
+    "eslint-plugin-inferno": "^7.33.3",
+    "eslint-plugin-jsx-a11y": "^6.7.1",
+    "eslint-plugin-prettier": "^5.1.3",
+    "import-sort-style-module": "^6.0.0",
+    "lint-staged": "^15.2.0",
+    "prettier": "^3.2.4",
+    "prettier-plugin-import-sort": "^0.0.7",
+    "prettier-plugin-organize-imports": "^3.2.3",
+    "prettier-plugin-packagejson": "^2.4.9",
+    "rimraf": "^5.0.0",
+    "sortpack": "^2.4.0",
+    "style-loader": "^3.3.4",
+    "terser": "^5.27.0",
+    "typescript": "^5.3.3",
+    "typescript-language-server": "^4.3.1",
+    "webpack-bundle-analyzer": "^4.9.0",
+    "webpack-dev-server": "4.15.1"
+  },
+  "lint-staged": {
+    "*.{css, scss}": [
+      "prettier --write"
+    ],
+    "*.{ts,tsx,js}": [
+      "prettier --write",
+      "eslint --fix"
+    ],
+    "package.json": [
+      "sortpack"
+    ]
+  },
+  "packageManager": "yarn@1.22.19",
+  "engineStrict": true,
+  "importSort": {
+    ".js, .jsx, .ts, .tsx": {
+      "style": "module",
+      "parser": "typescript"
+    }
+  }
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/lemmy/pin.json b/nixpkgs/pkgs/servers/web-apps/lemmy/pin.json
new file mode 100644
index 000000000000..fdab1c9d63d6
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/lemmy/pin.json
@@ -0,0 +1,8 @@
+{
+  "serverVersion": "0.19.3",
+  "uiVersion": "0.19.3",
+  "serverHash": "sha256-iO7bY2oChx0cZbwgXMrrV4e1kffop9s4xmepNywnApU=",
+  "serverCargoHash": "sha256-XXfg0o/LQ/imnsHsREoBXMDP1hU5Stxv0s6AP+o+USc=",
+  "uiHash": "sha256-6GGiKCNL0PALdz0W0d1OOPyMIA5kaoL3148j9GWzrMM=",
+  "uiYarnDepsHash": "sha256-UQ+B2vF34L+HuisyO7wdW2zCfEEGa8YdnoaB4jHi+DY="
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/lemmy/server.nix b/nixpkgs/pkgs/servers/web-apps/lemmy/server.nix
new file mode 100644
index 000000000000..4f605b0b2dbd
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/lemmy/server.nix
@@ -0,0 +1,64 @@
+{ lib
+, stdenv
+, rustPlatform
+, fetchFromGitHub
+, openssl
+, postgresql
+, libiconv
+, Security
+, protobuf
+, rustfmt
+, nixosTests
+}:
+let
+  pinData = lib.importJSON ./pin.json;
+  version = pinData.serverVersion;
+in
+rustPlatform.buildRustPackage rec {
+  inherit version;
+  pname = "lemmy-server";
+
+  src = fetchFromGitHub {
+    owner = "LemmyNet";
+    repo = "lemmy";
+    rev = version;
+    hash = pinData.serverHash;
+    fetchSubmodules = true;
+  };
+
+  preConfigure = ''
+    echo 'pub const VERSION: &str = "${version}";' > crates/utils/src/version.rs
+  '';
+
+  cargoHash = pinData.serverCargoHash;
+
+  buildInputs = [ postgresql ]
+    ++ lib.optionals stdenv.isDarwin [ libiconv Security ];
+
+  # Using OPENSSL_NO_VENDOR is not an option on darwin
+  # As of version 0.10.35 rust-openssl looks for openssl on darwin
+  # with a hardcoded path to /usr/lib/libssl.x.x.x.dylib
+  # https://github.com/sfackler/rust-openssl/blob/master/openssl-sys/build/find_normal.rs#L115
+  OPENSSL_LIB_DIR = "${lib.getLib openssl}/lib";
+  OPENSSL_INCLUDE_DIR = "${openssl.dev}/include";
+
+  PROTOC = "${protobuf}/bin/protoc";
+  PROTOC_INCLUDE = "${protobuf}/include";
+  nativeBuildInputs = [ protobuf rustfmt ];
+
+  checkFlags = [
+    # test requires database access
+    "--skip=session_middleware::tests::test_session_auth"
+  ];
+
+  passthru.updateScript = ./update.py;
+  passthru.tests.lemmy-server = nixosTests.lemmy;
+
+  meta = with lib; {
+    description = "🐀 Building a federated alternative to reddit in rust";
+    homepage = "https://join-lemmy.org/";
+    license = licenses.agpl3Only;
+    maintainers = with maintainers; [ happysalada billewanick ];
+    mainProgram = "lemmy_server";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/lemmy/ui.nix b/nixpkgs/pkgs/servers/web-apps/lemmy/ui.nix
new file mode 100644
index 000000000000..2bb1ccaeb842
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/lemmy/ui.nix
@@ -0,0 +1,98 @@
+{ lib
+, mkYarnPackage
+, libsass
+, nodejs
+, python3
+, pkg-config
+, fetchFromGitHub
+, fetchYarnDeps
+, nixosTests
+, vips
+, nodePackages
+}:
+
+let
+  pinData = lib.importJSON ./pin.json;
+
+  pkgConfig = {
+    node-sass = {
+      nativeBuildInputs = [ pkg-config ];
+      buildInputs = [ libsass python3 ];
+      postInstall = ''
+        LIBSASS_EXT=auto yarn --offline run build
+        rm build/config.gypi
+      '';
+    };
+    sharp = {
+      nativeBuildInputs = [ pkg-config nodePackages.node-gyp nodePackages.semver ];
+      buildInputs = [ vips ];
+      postInstall = ''
+        yarn --offline run install
+      '';
+    };
+  };
+
+  name = "lemmy-ui";
+  version = pinData.uiVersion;
+
+  src = fetchFromGitHub {
+    owner = "LemmyNet";
+    repo = name;
+    rev = version;
+    fetchSubmodules = true;
+    hash = pinData.uiHash;
+  };
+in
+mkYarnPackage {
+
+  inherit src pkgConfig name version;
+
+  extraBuildInputs = [ libsass ];
+
+  packageJSON = ./package.json;
+  offlineCache = fetchYarnDeps {
+    yarnLock = src + "/yarn.lock";
+    hash = pinData.uiYarnDepsHash;
+  };
+
+  patchPhase = ''
+    substituteInPlace ./package.json \
+      --replace '$(git rev-parse --short HEAD)' "${src.rev}" \
+      --replace 'yarn clean' 'yarn --offline clean' \
+      --replace 'yarn run rimraf dist' 'yarn --offline run rimraf dist'
+  '';
+
+  yarnPreBuild = ''
+    export npm_config_nodedir=${nodejs}
+  '';
+
+  buildPhase = ''
+    # Yarn writes cache directories etc to $HOME.
+    export HOME=$PWD/yarn_home
+
+    ln -sf $PWD/node_modules $PWD/deps/lemmy-ui/
+    echo 'export const VERSION = "${version}";' > $PWD/deps/lemmy-ui/src/shared/version.ts
+
+    yarn --offline build:prod
+  '';
+
+  preInstall = ''
+    mkdir $out
+    cp -R ./deps/lemmy-ui/dist $out
+    cp -R ./node_modules $out
+  '';
+
+  distPhase = "true";
+
+  passthru.updateScript = ./update.py;
+  passthru.tests.lemmy-ui = nixosTests.lemmy;
+  passthru.commit_sha = src.rev;
+
+  meta = with lib; {
+    description = "Building a federated alternative to reddit in rust";
+    homepage = "https://join-lemmy.org/";
+    license = licenses.agpl3Only;
+    maintainers = with maintainers; [ happysalada billewanick ];
+    inherit (nodejs.meta) platforms;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/lemmy/update.py b/nixpkgs/pkgs/servers/web-apps/lemmy/update.py
new file mode 100755
index 000000000000..4e867553b790
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/lemmy/update.py
@@ -0,0 +1,163 @@
+#! /usr/bin/env nix-shell
+#! nix-shell -i python3 -p python3 python3.pkgs.semver nix-prefetch-github
+from urllib.request import Request, urlopen
+import dataclasses
+import subprocess
+import os.path
+import semver
+from typing import (
+    Optional,
+    Dict,
+    List,
+)
+import json
+import os
+
+
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+NIXPKGS = os.path.abspath(os.path.join(SCRIPT_DIR, "../../../../"))
+
+
+OWNER = "LemmyNet"
+UI_REPO = "lemmy-ui"
+SERVER_REPO = "lemmy"
+
+
+@dataclasses.dataclass
+class Pin:
+    serverVersion: str
+    uiVersion: str
+    serverHash: str = ""
+    serverCargoHash: str = ""
+    uiHash: str = ""
+    uiYarnDepsHash: str = ""
+
+    filename: Optional[str] = None
+
+    def write(self) -> None:
+        if not self.filename:
+            raise ValueError("No filename set")
+
+        with open(self.filename, "w") as fd:
+            pin = dataclasses.asdict(self)
+            del pin["filename"]
+            json.dump(pin, fd, indent=2)
+            fd.write("\n")
+
+
+def github_get(path: str) -> Dict:
+    """Send a GET request to GitHub, optionally adding GITHUB_TOKEN auth header"""
+    url = f"https://api.github.com/{path.lstrip('/')}"
+    print(f"Retrieving {url}")
+
+    req = Request(url)
+
+    if "GITHUB_TOKEN" in os.environ:
+        req.add_header("authorization", f"Bearer {os.environ['GITHUB_TOKEN']}")
+
+    with urlopen(req) as resp:
+        return json.loads(resp.read())
+
+
+def get_latest_release(owner: str, repo: str) -> str:
+    return github_get(f"/repos/{owner}/{repo}/releases/latest")["tag_name"]
+
+
+def prefetch_github(owner: str, repo: str, rev: str) -> str:
+    """Prefetch GitHub rev and return SRI hash"""
+    print(f"Prefetching {owner}/{repo}({rev})")
+
+    proc = subprocess.run(
+        ["nix-prefetch-github", owner, repo, "--rev", rev, "--fetch-submodules"],
+        check=True,
+        stdout=subprocess.PIPE,
+    )
+
+    return json.loads(proc.stdout)["hash"]
+
+
+def get_latest_tag(owner: str, repo: str, prerelease: bool = False) -> str:
+    """Get the latest tag from a GitHub Repo"""
+    tags: List[str] = []
+
+    # As the GitHub API doesn't have any notion of "latest" for tags we need to
+    # collect all of them and sort so we can figure out the latest one.
+    i = 0
+    while i <= 100:  # Prevent infinite looping
+        i += 1
+        resp = github_get(f"/repos/{owner}/{repo}/tags?page={i}")
+        if not resp:
+            break
+
+        # Filter out unparseable tags
+        for tag in resp:
+            try:
+                parsed = semver.Version.parse(tag["name"])
+                if (
+                    semver.Version.parse(tag["name"])
+                    and not prerelease
+                    and parsed.prerelease
+                ):  # Filter out release candidates
+                    continue
+            except ValueError:
+                continue
+            else:
+                tags.append(tag["name"])
+
+    # Sort and return latest
+    return sorted(tags, key=lambda name: semver.Version.parse(name))[-1]
+
+
+def get_fod_hash(attr: str) -> str:
+    """
+    Get fixed output hash for attribute.
+    This depends on a fixed output derivation with an empty hash.
+    """
+
+    print(f"Getting fixed output hash for {attr}")
+
+    proc = subprocess.run(["nix-build", NIXPKGS, "-A", attr], stderr=subprocess.PIPE)
+    if proc.returncode != 1:
+        raise ValueError("Expected nix-build to fail")
+
+    # Iterate list in reverse order so we get the "got:" line early
+    for line in proc.stderr.decode().split("\n")[::-1]:
+        cols = line.split()
+        if cols and cols[0] == "got:":
+            return cols[1]
+
+    raise ValueError("No fixed output hash found")
+
+
+def make_server_pin(pin: Pin, attr: str) -> None:
+    pin.serverHash = prefetch_github(OWNER, SERVER_REPO, pin.serverVersion)
+    pin.write()
+    pin.serverCargoHash = get_fod_hash(attr)
+    pin.write()
+
+
+def make_ui_pin(pin: Pin, package_json: str, attr: str) -> None:
+    # Save a copy of package.json
+    print("Getting package.json")
+    with urlopen(
+        f"https://raw.githubusercontent.com/{OWNER}/{UI_REPO}/{pin.uiVersion}/package.json"
+    ) as resp:
+        with open(os.path.join(SCRIPT_DIR, package_json), "wb") as fd:
+            fd.write(resp.read())
+
+    pin.uiHash = prefetch_github(OWNER, UI_REPO, pin.uiVersion)
+    pin.write()
+    pin.uiYarnDepsHash = get_fod_hash(attr)
+    pin.write()
+
+
+if __name__ == "__main__":
+    # Get server version
+    server_version = get_latest_tag(OWNER, SERVER_REPO)
+
+    # Get UI version (not always the same as lemmy-server)
+    ui_version = get_latest_tag(OWNER, UI_REPO)
+
+    pin = Pin(server_version, ui_version, filename=os.path.join(SCRIPT_DIR, "pin.json"))
+    make_server_pin(pin, "lemmy-server")
+    make_ui_pin(pin, "package.json", "lemmy-ui")
diff --git a/nixpkgs/pkgs/servers/web-apps/linx-server/default.nix b/nixpkgs/pkgs/servers/web-apps/linx-server/default.nix
new file mode 100644
index 000000000000..995eacf792e4
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/linx-server/default.nix
@@ -0,0 +1,33 @@
+{ buildGoModule
+, fetchFromGitHub
+, go-rice
+, lib
+}:
+
+buildGoModule rec {
+  pname = "linx-server";
+  version = "unstable-2021-12-24";
+
+  src = fetchFromGitHub {
+    owner = "zizzydizzymc";
+    repo = pname;
+    rev = "3f503442f10fca68a3212975b23cf74d92c9988c";
+    hash = "sha256-tTHw/rIb2Gs5i5vZKsSgbUePIY7Np6HofBXu4TTjKbw=";
+  };
+
+  # upstream tests are broken, see zizzydizzymc/linx-server#34
+  patches = [ ./test.patch ];
+
+  vendorHash = "sha256-/N3AXrPyENp3li4X86LNXsfBYbjJulk+0EAyogPNIpc=";
+
+  nativeBuildInputs = [ go-rice ];
+
+  preBuild = "rice embed-go";
+
+  meta = with lib; {
+    description = "Self-hosted file/code/media sharing website.";
+    homepage = "https://put.icu";
+    license = licenses.gpl3Only;
+    maintainers = with maintainers; [ urandom ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/linx-server/test.patch b/nixpkgs/pkgs/servers/web-apps/linx-server/test.patch
new file mode 100644
index 000000000000..7303aecaf8ef
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/linx-server/test.patch
@@ -0,0 +1,74 @@
+diff --git a/server_test.go b/server_test.go
+index fc225ce..2df3608 100644
+--- a/server_test.go
++++ b/server_test.go
+@@ -446,63 +446,6 @@ func TestPostJSONUpload(t *testing.T) {
+ 	}
+ }
+ 
+-func TestPostJSONUploadMaxExpiry(t *testing.T) {
+-	mux := setup()
+-	Config.maxExpiry = 300
+-
+-	// include 0 to test edge case
+-	// https://github.com/andreimarcu/linx-server/issues/111
+-	testExpiries := []string{"86400", "-150", "0"}
+-	for _, expiry := range testExpiries {
+-		w := httptest.NewRecorder()
+-
+-		filename := generateBarename() + ".txt"
+-
+-		var b bytes.Buffer
+-		mw := multipart.NewWriter(&b)
+-		fw, err := mw.CreateFormFile("file", filename)
+-		if err != nil {
+-			t.Fatal(err)
+-		}
+-
+-		fw.Write([]byte("File content"))
+-		mw.Close()
+-
+-		req, err := http.NewRequest("POST", "/upload/", &b)
+-		req.Header.Set("Content-Type", mw.FormDataContentType())
+-		req.Header.Set("Accept", "application/json")
+-		req.Header.Set("Linx-Expiry", expiry)
+-		if err != nil {
+-			t.Fatal(err)
+-		}
+-
+-		mux.ServeHTTP(w, req)
+-
+-		if w.Code != 200 {
+-			t.Log(w.Body.String())
+-			t.Fatalf("Status code is not 200, but %d", w.Code)
+-		}
+-
+-		var myjson RespOkJSON
+-		err = json.Unmarshal([]byte(w.Body.String()), &myjson)
+-		if err != nil {
+-			t.Fatal(err)
+-		}
+-
+-		myExp, err := strconv.ParseInt(myjson.Expiry, 10, 64)
+-		if err != nil {
+-			t.Fatal(err)
+-		}
+-
+-		expected := time.Now().Add(time.Duration(Config.maxExpiry) * time.Second).Unix()
+-		if myExp != expected {
+-			t.Fatalf("File expiry is not %d but %s", expected, myjson.Expiry)
+-		}
+-	}
+-
+-	Config.maxExpiry = 0
+-}
+-
+ func TestPostExpiresJSONUpload(t *testing.T) {
+ 	mux := setup()
+ 	w := httptest.NewRecorder()
+@@ -1301,5 +1244,4 @@ func TestPutAndGetCLI(t *testing.T) {
+ 	if !strings.HasPrefix(contentType, "text/plain") {
+ 		t.Fatalf("Didn't receive file directly but %s", contentType)
+ 	}
+-
+ }
diff --git a/nixpkgs/pkgs/servers/web-apps/livebook/default.nix b/nixpkgs/pkgs/servers/web-apps/livebook/default.nix
new file mode 100644
index 000000000000..e1815a819bbf
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/livebook/default.nix
@@ -0,0 +1,42 @@
+{ lib, beamPackages, makeWrapper, rebar3, elixir, erlang, fetchFromGitHub, nixosTests }:
+beamPackages.mixRelease rec {
+  pname = "livebook";
+  version = "0.12.1";
+
+  inherit elixir;
+
+  buildInputs = [ erlang ];
+
+  nativeBuildInputs = [ makeWrapper ];
+
+  src = fetchFromGitHub {
+    owner = "livebook-dev";
+    repo = "livebook";
+    rev = "v${version}";
+    hash = "sha256-Q4c0AelZZDPxE/rtoHIRQi3INMLHeiZ72TWgy183f4Q=";
+  };
+
+  mixFodDeps = beamPackages.fetchMixDeps {
+    pname = "mix-deps-${pname}";
+    inherit src version;
+    hash = "sha256-dyKhrbb7vazBV6LFERtGHLQXEx29vTgn074mY4fsHy4=";
+  };
+
+  postInstall = ''
+    wrapProgram $out/bin/livebook \
+      --prefix PATH : ${lib.makeBinPath [ elixir erlang ]} \
+      --set MIX_REBAR3 ${rebar3}/bin/rebar3
+    '';
+
+  passthru.tests = {
+    livebook-service = nixosTests.livebook-service;
+  };
+
+  meta = with lib; {
+    license = licenses.asl20;
+    homepage = "https://livebook.dev/";
+    description = "Automate code & data workflows with interactive Elixir notebooks";
+    maintainers = with maintainers; [ munksgaard ];
+    platforms = platforms.unix;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/matomo/bootstrap.php b/nixpkgs/pkgs/servers/web-apps/matomo/bootstrap.php
new file mode 100644
index 000000000000..a8163f33e5c0
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/matomo/bootstrap.php
@@ -0,0 +1,6 @@
+<?php
+// get PIWIK_USER_PATH from environment variable,
+// so this bootstrap.php can be read-only but still configure PIWIK_USER_PATH at runtime
+if ($path = getenv('PIWIK_USER_PATH')) {
+  define('PIWIK_USER_PATH', $path);
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/matomo/change-path-geoip2-4.x.patch b/nixpkgs/pkgs/servers/web-apps/matomo/change-path-geoip2-4.x.patch
new file mode 100644
index 000000000000..5e3b32f2ef8c
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/matomo/change-path-geoip2-4.x.patch
@@ -0,0 +1,10 @@
+--- a/plugins/GeoIp2/config/config.php
++++ b/plugins/GeoIp2/config/config.php
+@@ -1,6 +1,6 @@
+ <?php
+ 
+ return [
+-    'path.geoip2' => DI\string('{path.root}/misc/'),
++    'path.geoip2' => PIWIK_USER_PATH . '/misc/',
+     'geopip2.ispEnabled' => true
+ ];
diff --git a/nixpkgs/pkgs/servers/web-apps/matomo/change-path-geoip2-5.x.patch b/nixpkgs/pkgs/servers/web-apps/matomo/change-path-geoip2-5.x.patch
new file mode 100644
index 000000000000..601e0815cb6e
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/matomo/change-path-geoip2-5.x.patch
@@ -0,0 +1,10 @@
+--- a/plugins/GeoIp2/config/config.php
++++ b/plugins/GeoIp2/config/config.php
+@@ -1,6 +1,6 @@
+ <?php
+ 
+ return [
+-    'path.geoip2' => Piwik\DI::string('{path.root}/misc/'),
++    'path.geoip2' => PIWIK_USER_PATH . '/misc/',
+     'geopip2.ispEnabled' => true
+ ];
diff --git a/nixpkgs/pkgs/servers/web-apps/matomo/default.nix b/nixpkgs/pkgs/servers/web-apps/matomo/default.nix
new file mode 100644
index 000000000000..c9584fb25e35
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/matomo/default.nix
@@ -0,0 +1,125 @@
+{ lib, stdenv, fetchurl, makeWrapper, php, nixosTests }:
+
+let
+  versions = {
+    matomo = {
+      version = "4.16.1";
+      hash = "sha256-cGnsxfpvt7FyhxFcA2/gWWe7CyanVGZVKtCDES3XLdI=";
+    };
+    matomo_5 = {
+      version = "5.0.2";
+      hash = "sha256-rLAShJLtzd3HB1Je+P+i8GKWdeklyC2sTnmPR07Md+8=";
+    };
+    matomo-beta = {
+      version = "5.0.0";
+      # `beta` examples: "b1", "rc1", null
+      # when updating: use null if stable version is >= latest beta or release candidate
+      beta = "rc9";
+      hash = "sha256-OXxJCEXcrl6UXYh+jbNqLQGYphrSjxaOAZg3AZVPAqs=";
+    };
+  };
+  common = pname: { version, hash, beta ? null }:
+    let
+      fullVersion = version + lib.optionalString (beta != null) "-${toString beta}";
+      name = "${pname}-${fullVersion}";
+    in
+
+      stdenv.mkDerivation rec {
+        inherit name;
+        version = fullVersion;
+
+        src = fetchurl {
+          url = "https://builds.matomo.org/matomo-${version}.tar.gz";
+          inherit hash;
+        };
+
+        nativeBuildInputs = [ makeWrapper ];
+
+        patches = [
+          # This changes the default value of the database server field
+          # from 127.0.0.1 to localhost.
+          # unix socket authentication only works with localhost,
+          # but password-based SQL authentication works with both.
+          # TODO: is upstream interested in this?
+          # -> discussion at https://github.com/matomo-org/matomo/issues/12646
+          ./make-localhost-default-database-host.patch
+          # This changes the default config for path.geoip2 so that it doesn't point
+          # to the nix store.
+          (if lib.versionOlder version "5.0"
+           then ./change-path-geoip2-4.x.patch
+           else ./change-path-geoip2-5.x.patch)
+        ];
+
+        # this bootstrap.php adds support for getting PIWIK_USER_PATH
+        # from an environment variable. Point it to a mutable location
+        # to be able to use matomo read-only from the nix store
+        postPatch = ''
+          cp ${./bootstrap.php} bootstrap.php
+        '';
+
+        # TODO: future versions might rename the PIWIK_… variables to MATOMO_…
+        # TODO: Move more unnecessary files from share/, especially using PIWIK_INCLUDE_PATH.
+        #       See https://forum.matomo.org/t/bootstrap-php/5926/10 and
+        #       https://github.com/matomo-org/matomo/issues/11654#issuecomment-297730843
+        installPhase = ''
+          runHook preInstall
+
+          # copy everything to share/, used as webroot folder, and then remove what's known to be not needed
+          mkdir -p $out/share
+          cp -ra * $out/share/
+          # tmp/ is created by matomo in PIWIK_USER_PATH
+          rmdir $out/share/tmp
+          # config/ needs to be accessed by PIWIK_USER_PATH anyway
+          ln -s $out/share/config $out/
+
+          makeWrapper ${php}/bin/php $out/bin/matomo-console \
+            --add-flags "$out/share/console"
+
+          runHook postInstall
+        '';
+
+        filesToFix = [
+          "misc/composer/build-xhprof.sh"
+          "misc/composer/clean-xhprof.sh"
+          "misc/cron/archive.sh"
+          "plugins/GeoIp2/config/config.php"
+          "plugins/Installation/FormDatabaseSetup.php"
+          "vendor/pear/archive_tar/sync-php4"
+          "vendor/szymach/c-pchart/coverage.sh"
+          "vendor/matomo/matomo-php-tracker/run_tests.sh"
+          "vendor/twig/twig/drupal_test.sh"
+        ];
+
+        # This fixes the consistency check in the admin interface
+        #
+        # The filesToFix list may contain files that are exclusive to only one of the versions we build
+        # make sure to test for existence to avoid erroring on an incompatible version and failing
+        postFixup = ''
+          pushd $out/share > /dev/null
+          for f in $filesToFix; do
+            if [ -f "$f" ]; then
+              length="$(wc -c "$f" | cut -d' ' -f1)"
+              hash="$(md5sum "$f" | cut -d' ' -f1)"
+              sed -i "s:\\(\"$f\"[^(]*(\\).*:\\1\"$length\", \"$hash\"),:g" config/manifest.inc.php
+            else
+              echo "INFO(files-to-fix): $f does not exist in this version"
+            fi
+          done
+          popd > /dev/null
+        '';
+
+        passthru = {
+          tests = nixosTests.matomo."${pname}";
+        };
+
+        meta = with lib; {
+          description = "A real-time web analytics application";
+          mainProgram = "matomo-console";
+          license = licenses.gpl3Plus;
+          homepage = "https://matomo.org/";
+          platforms = platforms.all;
+          maintainers = with maintainers; [ florianjacob kiwi sebbel twey boozedog ] ++ teams.flyingcircus.members;
+        };
+      };
+in
+lib.mapAttrs common versions
diff --git a/nixpkgs/pkgs/servers/web-apps/matomo/make-localhost-default-database-host.patch b/nixpkgs/pkgs/servers/web-apps/matomo/make-localhost-default-database-host.patch
new file mode 100644
index 000000000000..5af8ef860b2f
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/matomo/make-localhost-default-database-host.patch
@@ -0,0 +1,13 @@
+diff --git a/plugins/Installation/FormDatabaseSetup.php b/plugins/Installation/FormDatabaseSetup.php
+index 74de2535b4..bc172ad0eb 100644
+--- a/plugins/Installation/FormDatabaseSetup.php
++++ b/plugins/Installation/FormDatabaseSetup.php
+@@ -82,7 +82,7 @@ class FormDatabaseSetup extends QuickForm2
+ 
+ 
+         $defaults = array(
+-            'host'          => '127.0.0.1',
++            'host'          => 'localhost',
+             'type'          => $defaultDatabaseType,
+             'tables_prefix' => 'matomo_',
+         );
diff --git a/nixpkgs/pkgs/servers/web-apps/mediawiki/default.nix b/nixpkgs/pkgs/servers/web-apps/mediawiki/default.nix
new file mode 100644
index 000000000000..23f0e6c2153c
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/mediawiki/default.nix
@@ -0,0 +1,39 @@
+{ lib, stdenvNoCC, fetchurl, nixosTests }:
+
+stdenvNoCC.mkDerivation rec {
+  pname = "mediawiki";
+  version = "1.41.0";
+
+  src = fetchurl {
+    url = "https://releases.wikimedia.org/mediawiki/${lib.versions.majorMinor version}/mediawiki-${version}.tar.gz";
+    hash = "sha256-84Qrcqp6JYiPHsYyMj3YkEF3OaEg2VHEhfhQ4MzLQhs=";
+  };
+
+  postPatch = ''
+    sed -i 's|$vars = Installer::getExistingLocalSettings();|$vars = null;|' includes/installer/CliInstaller.php
+  '';
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir -p $out/share/mediawiki
+    cp -r * $out/share/mediawiki
+    echo "<?php
+      return require(getenv('MEDIAWIKI_CONFIG'));
+    ?>" > $out/share/mediawiki/LocalSettings.php
+
+    runHook postInstall
+  '';
+
+  passthru.tests = {
+    inherit (nixosTests.mediawiki) mysql postgresql;
+  };
+
+  meta = with lib; {
+    description = "The collaborative editing software that runs Wikipedia";
+    license = licenses.gpl2Plus;
+    homepage = "https://www.mediawiki.org/";
+    platforms = platforms.all;
+    maintainers = with maintainers; [ ] ++ teams.c3d2.members;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/meme-bingo-web/default.nix b/nixpkgs/pkgs/servers/web-apps/meme-bingo-web/default.nix
new file mode 100644
index 000000000000..6a0228899f08
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/meme-bingo-web/default.nix
@@ -0,0 +1,35 @@
+{ lib, fetchFromGitea, rustPlatform, makeWrapper }:
+
+rustPlatform.buildRustPackage rec {
+  pname = "meme-bingo-web";
+  version = "0.2.0";
+
+  src = fetchFromGitea {
+    domain = "codeberg.org";
+    owner = "annaaurora";
+    repo = "meme-bingo-web";
+    rev = "v${version}";
+    hash = "sha256-6hQra+10TaaQGzwiYfL+WHmGc6f0Hn8Tybd0lA5t0qc=";
+  };
+
+  cargoHash = "sha256-/hBymxNAzyfapUL5Whkg4NBLA7Fc8A1npXEa9MXTAz4=";
+
+  nativeBuildInputs = [ makeWrapper ];
+
+  postInstall = ''
+    mkdir -p $out/share/meme-bingo-web
+    cp -r {templates,static} $out/share/meme-bingo-web/
+
+    wrapProgram $out/bin/meme-bingo-web \
+      --set MEME_BINGO_TEMPLATES $out/share/meme-bingo-web/templates \
+      --set MEME_BINGO_STATIC $out/share/meme-bingo-web/static
+  '';
+
+  meta = with lib; {
+    description = "Play meme bingo using this neat web app";
+    mainProgram = "meme-bingo-web";
+    homepage = "https://codeberg.org/annaaurora/meme-bingo-web";
+    license = licenses.unlicense;
+    maintainers = with maintainers; [ annaaurora ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/monica/default.nix b/nixpkgs/pkgs/servers/web-apps/monica/default.nix
new file mode 100644
index 000000000000..69d9aae3b186
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/monica/default.nix
@@ -0,0 +1,39 @@
+{
+  stdenv,
+  lib,
+  fetchurl,
+  nixosTests,
+  dataDir ? "/var/lib/monica",
+}:
+stdenv.mkDerivation rec {
+  pname = "monica";
+  version = "4.0.0";
+
+  src = fetchurl {
+    url = "https://github.com/monicahq/monica/releases/download/v${version}/monica-v${version}.tar.bz2";
+    hash = "sha256-uHsRCO7P5w1JmKDwyLUVjK6NwnTF2mjsz0hOnPrms+w=";
+  };
+
+  dontBuild = true;
+
+  installPhase = ''
+    mkdir $out
+    cp -R * $out/
+    rm -rf $out/storage
+    ln -s ${dataDir}/.env $out/.env
+    ln -s ${dataDir}/storage $out/storage
+  '';
+
+  passthru.tests.monica = nixosTests.monica;
+
+  meta = {
+    description = "Personal CRM";
+    homepage = "https://www.monicahq.com/";
+    longDescription = ''
+      Remember everything about your friends, family and business
+      relationships.
+    '';
+    license = lib.licenses.agpl3Plus;
+    platforms = lib.platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/moodle/default.nix b/nixpkgs/pkgs/servers/web-apps/moodle/default.nix
new file mode 100644
index 000000000000..79fb83749e60
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/moodle/default.nix
@@ -0,0 +1,71 @@
+{ lib, stdenv, fetchurl, writeText, plugins ? [ ], nixosTests }:
+
+let
+  version = "4.3.3";
+
+  versionParts = lib.take 2 (lib.splitVersion version);
+  # 4.2 -> 402, 3.11 -> 311
+  stableVersion = lib.removePrefix "0" (lib.concatMapStrings
+    (p: if (lib.toInt p) < 10 then (lib.concatStrings ["0" p]) else p)
+    versionParts);
+
+in stdenv.mkDerivation rec {
+  pname = "moodle";
+  inherit version;
+
+  src = fetchurl {
+    url = "https://download.moodle.org/download.php/direct/stable${stableVersion}/${pname}-${version}.tgz";
+    hash = "sha256-yFrD277bO25O5GeXVG4VhKO/oH9dsgqoTsrlMZoXHbI=";
+  };
+
+  phpConfig = writeText "config.php" ''
+    <?php
+      return require(getenv('MOODLE_CONFIG'));
+    ?>
+  '';
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir -p $out/share/moodle
+    cp -r . $out/share/moodle
+    cp ${phpConfig} $out/share/moodle/config.php
+
+    ${lib.concatStringsSep "\n" (map (p:
+      let
+        dir = if p.pluginType == "mod" then
+          "mod"
+        else if p.pluginType == "theme" then
+          "theme"
+        else if p.pluginType == "block" then
+          "blocks"
+        else if p.pluginType == "question" then
+          "question/type"
+        else if p.pluginType == "course" then
+          "course/format"
+        else if p.pluginType == "report" then
+          "admin/report"
+        else
+          throw "unknown moodle plugin type";
+        # we have to copy it, because the plugins have refrences to .. inside
+      in ''
+        mkdir -p $out/share/moodle/${dir}/${p.name}
+        cp -r ${p}/* $out/share/moodle/${dir}/${p.name}/
+      '') plugins)}
+
+    runHook postInstall
+  '';
+
+  passthru.tests = {
+    inherit (nixosTests) moodle;
+  };
+
+  meta = with lib; {
+    description =
+      "Free and open-source learning management system (LMS) written in PHP";
+    license = licenses.gpl3Plus;
+    homepage = "https://moodle.org/";
+    maintainers = with maintainers; [ freezeboy ];
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/moodle/moodle-utils.nix b/nixpkgs/pkgs/servers/web-apps/moodle/moodle-utils.nix
new file mode 100644
index 000000000000..090d87cb1ee8
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/moodle/moodle-utils.nix
@@ -0,0 +1,33 @@
+{ stdenv, unzip, ... }:
+
+let
+  buildMoodlePlugin = a@{
+    name,
+    src,
+    pluginType,
+    configurePhase ? ":",
+    buildPhase ? ":",
+    buildInputs ? [ ],
+    nativeBuildInputs ? [ ],
+    ...
+  }:
+  stdenv.mkDerivation (a // {
+    name = name;
+
+    inherit pluginType;
+    inherit configurePhase buildPhase buildInputs;
+
+    nativeBuildInputs = [ unzip ] ++ nativeBuildInputs;
+
+    installPhase = ''
+      runHook preInstall
+
+      mkdir -p "$out"
+      mv * $out/
+
+      runHook postInstall
+    '';
+  });
+in {
+  inherit buildMoodlePlugin;
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/morty/default.nix b/nixpkgs/pkgs/servers/web-apps/morty/default.nix
new file mode 100644
index 000000000000..b44d2e03bf16
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/morty/default.nix
@@ -0,0 +1,29 @@
+{ lib, buildGoModule, fetchFromGitHub }:
+
+buildGoModule {
+  pname = "morty";
+  version = "unstable-2021-04-22";
+
+  src = fetchFromGitHub {
+    owner = "asciimoo";
+    repo = "morty";
+    rev = "f5bff1e285d3f973cacf73318e55175edafd633f";
+    sha256 = "sha256-ik2VAPdxllt76UVFt77c1ltxIwFNahAKjn3FuErNFYo=";
+  };
+
+  vendorHash = "sha256-3sllcoTDYQBAyAT7e9KeKNrlTEbgnoZc0Vt0ksQByvo=";
+
+  meta = with lib; {
+    description = "Privacy aware web content sanitizer proxy as a service";
+    mainProgram = "morty";
+    longDescription = ''
+      Morty rewrites web pages to exclude malicious HTML tags and attributes.
+      It also replaces external resource references to prevent third party information leaks.
+
+      The main goal of morty is to provide a result proxy for searx, but it can be used as a standalone sanitizer service too.
+    '';
+    homepage = "https://github.com/asciimoo/morty";
+    maintainers = with maintainers; [ leenaars SuperSandro2000 ];
+    license = licenses.agpl3Only;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/netbox/config.patch b/nixpkgs/pkgs/servers/web-apps/netbox/config.patch
new file mode 100644
index 000000000000..a2e0b0b95a87
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/netbox/config.patch
@@ -0,0 +1,50 @@
+diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py
+index 2de06dd10..00406af48 100644
+--- a/netbox/netbox/settings.py
++++ b/netbox/netbox/settings.py
+@@ -236,6 +236,7 @@ TASKS_REDIS_DATABASE = TASKS_REDIS.get('DATABASE', 0)
+ TASKS_REDIS_SSL = TASKS_REDIS.get('SSL', False)
+ TASKS_REDIS_SKIP_TLS_VERIFY = TASKS_REDIS.get('INSECURE_SKIP_TLS_VERIFY', False)
+ TASKS_REDIS_CA_CERT_PATH = TASKS_REDIS.get('CA_CERT_PATH', False)
++TASKS_REDIS_URL = TASKS_REDIS.get('URL')
+ 
+ # Caching
+ if 'caching' not in REDIS:
+@@ -253,11 +254,12 @@ CACHING_REDIS_SENTINEL_SERVICE = REDIS['caching'].get('SENTINEL_SERVICE', 'defau
+ CACHING_REDIS_PROTO = 'rediss' if REDIS['caching'].get('SSL', False) else 'redis'
+ CACHING_REDIS_SKIP_TLS_VERIFY = REDIS['caching'].get('INSECURE_SKIP_TLS_VERIFY', False)
+ CACHING_REDIS_CA_CERT_PATH = REDIS['caching'].get('CA_CERT_PATH', False)
++CACHING_REDIS_URL = REDIS['caching'].get('URL', f'{CACHING_REDIS_PROTO}://{CACHING_REDIS_HOST}:{CACHING_REDIS_PORT}/{CACHING_REDIS_DATABASE}')
+ 
+ CACHES = {
+     'default': {
+         'BACKEND': 'django_redis.cache.RedisCache',
+-        'LOCATION': f'{CACHING_REDIS_PROTO}://{CACHING_REDIS_USERNAME_HOST}:{CACHING_REDIS_PORT}/{CACHING_REDIS_DATABASE}',
++        'LOCATION': CACHING_REDIS_URL,
+         'OPTIONS': {
+             'CLIENT_CLASS': 'django_redis.client.DefaultClient',
+             'PASSWORD': CACHING_REDIS_PASSWORD,
+@@ -410,7 +412,7 @@ USE_X_FORWARDED_HOST = True
+ X_FRAME_OPTIONS = 'SAMEORIGIN'
+ 
+ # Static files (CSS, JavaScript, Images)
+-STATIC_ROOT = BASE_DIR + '/static'
++STATIC_ROOT = getattr(configuration, 'STATIC_ROOT', os.path.join(BASE_DIR, 'static')).rstrip('/')
+ STATIC_URL = f'/{BASE_PATH}static/'
+ STATICFILES_DIRS = (
+     os.path.join(BASE_DIR, 'project-static', 'dist'),
+@@ -640,6 +642,14 @@ if TASKS_REDIS_USING_SENTINEL:
+             'socket_connect_timeout': TASKS_REDIS_SENTINEL_TIMEOUT
+         },
+     }
++elif TASKS_REDIS_URL:
++    RQ_PARAMS = {
++        'URL': TASKS_REDIS_URL,
++        'PASSWORD': TASKS_REDIS_PASSWORD,
++        'SSL': TASKS_REDIS_SSL,
++        'SSL_CERT_REQS': None if TASKS_REDIS_SKIP_TLS_VERIFY else 'required',
++        'DEFAULT_TIMEOUT': RQ_DEFAULT_TIMEOUT,
++    }
+ else:
+     RQ_PARAMS = {
+         'HOST': TASKS_REDIS_HOST,
diff --git a/nixpkgs/pkgs/servers/web-apps/netbox/default.nix b/nixpkgs/pkgs/servers/web-apps/netbox/default.nix
new file mode 100644
index 000000000000..494513648c9b
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/netbox/default.nix
@@ -0,0 +1,38 @@
+{ lib, nixosTests, callPackage, }:
+let
+  generic = import ./generic.nix;
+in
+lib.fix (self: {
+  netbox = self.netbox_3_7;
+
+  netbox_3_6 = callPackage generic {
+    version = "3.6.9";
+    hash = "sha256-R/hcBKrylW3GnEy10DkrLVr8YJtsSCvCP9H9LhafO9I=";
+    extraPatches = [
+      # Allow setting the STATIC_ROOT from within the configuration and setting a custom redis URL
+      ./config.patch
+    ];
+    tests = {
+      netbox = nixosTests.netbox_3_6;
+      inherit (nixosTests) netbox-upgrade;
+    };
+
+    maintainers = with lib.maintainers; [ minijackson n0emis raitobezarius ];
+    eol = true;
+  };
+
+  netbox_3_7 = callPackage generic {
+    version = "3.7.3";
+    hash = "sha256-8apjw3mO3RKT/IgJOG1+2GSjNwFhddZ9rIChdP26leE=";
+    extraPatches = [
+      # Allow setting the STATIC_ROOT from within the configuration and setting a custom redis URL
+      ./config.patch
+    ];
+    tests = {
+      netbox = nixosTests.netbox_3_7;
+      inherit (nixosTests) netbox-upgrade;
+    };
+
+    maintainers = with lib.maintainers; [ minijackson n0emis raitobezarius ];
+  };
+})
diff --git a/nixpkgs/pkgs/servers/web-apps/netbox/generic.nix b/nixpkgs/pkgs/servers/web-apps/netbox/generic.nix
new file mode 100644
index 000000000000..862b817be90e
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/netbox/generic.nix
@@ -0,0 +1,112 @@
+{ lib
+, fetchFromGitHub
+, python3
+, version
+, hash
+, plugins ? ps: []
+, extraPatches ? []
+, tests ? {}
+, maintainers ? []
+, eol ? false
+}:
+  let
+    extraBuildInputs = plugins python3.pkgs;
+  in
+  python3.pkgs.buildPythonApplication rec {
+      pname = "netbox";
+      inherit version;
+
+      format = "other";
+
+      src = fetchFromGitHub {
+        owner = "netbox-community";
+        repo = pname;
+        rev = "refs/tags/v${version}";
+        inherit hash;
+      };
+
+      patches = extraPatches;
+
+      propagatedBuildInputs = with python3.pkgs; [
+        bleach
+        boto3
+        django_4
+        django-cors-headers
+        django-debug-toolbar
+        django-filter
+        django-graphiql-debug-toolbar
+        django-mptt
+        django-pglocks
+        django-prometheus
+        django-redis
+        django-rq
+        django-tables2
+        django-taggit
+        django-timezone-field
+        djangorestframework
+        drf-spectacular
+        drf-spectacular-sidecar
+        drf-yasg
+        dulwich
+        swagger-spec-validator # from drf-yasg[validation]
+        feedparser
+        graphene-django
+        jinja2
+        markdown
+        markdown-include
+        netaddr
+        pillow
+        psycopg2
+        pyyaml
+        requests
+        sentry-sdk
+        social-auth-core
+        social-auth-app-django
+        svgwrite
+        tablib
+        jsonschema
+      ] ++ extraBuildInputs;
+
+      buildInputs = with python3.pkgs; [
+        mkdocs-material
+        mkdocs-material-extensions
+        mkdocstrings
+        mkdocstrings-python
+      ];
+
+      nativeBuildInputs = [
+        python3.pkgs.mkdocs
+      ];
+
+      postBuild = ''
+        PYTHONPATH=$PYTHONPATH:netbox/
+        python -m mkdocs build
+      '';
+
+      installPhase = ''
+        mkdir -p $out/opt/netbox
+        cp -r . $out/opt/netbox
+        chmod +x $out/opt/netbox/netbox/manage.py
+        makeWrapper $out/opt/netbox/netbox/manage.py $out/bin/netbox \
+          --prefix PYTHONPATH : "$PYTHONPATH"
+      '';
+
+      passthru = {
+        # PYTHONPATH of all dependencies used by the package
+        pythonPath = python3.pkgs.makePythonPath propagatedBuildInputs;
+        gunicorn = python3.pkgs.gunicorn;
+        inherit tests;
+      };
+
+      meta = {
+        homepage = "https://github.com/netbox-community/netbox";
+        description = "IP address management (IPAM) and data center infrastructure management (DCIM) tool";
+        mainProgram = "netbox";
+        license = lib.licenses.asl20;
+        knownVulnerabilities = (lib.optional eol "Netbox version ${version} is EOL; please upgrade by following the current release notes instructions.");
+        # Warning:
+        # Notice the missing `lib` in the inherit: it is using this function argument rather than a `with lib;` argument.
+        # If you replace this by `with lib;`, pay attention it does not inherit all maintainers in nixpkgs.
+        inherit maintainers;
+      };
+    }
diff --git a/nixpkgs/pkgs/servers/web-apps/nifi/default.nix b/nixpkgs/pkgs/servers/web-apps/nifi/default.nix
new file mode 100644
index 000000000000..6711608e2f50
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/nifi/default.nix
@@ -0,0 +1,46 @@
+{ lib, stdenv, fetchzip, makeWrapper, jdk11, nixosTests }:
+
+stdenv.mkDerivation rec {
+  pname = "nifi";
+  version = "1.25.0";
+
+  src = fetchzip {
+    url = "mirror://apache/nifi/${version}/nifi-${version}-bin.zip";
+    hash = "sha256-k8F4Zu1X/R2tv4ZsMT7K8VdXFKX3iLPIWG+gvyNjrf0=";
+  };
+
+  nativeBuildInputs = [ makeWrapper ];
+  buildInputs = [ jdk11 ];
+
+  installPhase = ''
+    cp -r ../$sourceRoot $out
+    rm -f $out/bin/*bat
+    rm -rf $out/extensions
+    mkdir -p $out/share/nifi
+    mv $out/conf $out/share/nifi
+    mv $out/docs $out/share/nifi
+    mv $out/{LICENSE,NOTICE,README} $out/share/nifi
+
+    substituteInPlace $out/bin/nifi.sh \
+      --replace "/bin/sh" "${stdenv.shell}"
+    substituteInPlace $out/bin/nifi-env.sh \
+      --replace "#export JAVA_HOME=/usr/java/jdk1.8.0/" "export JAVA_HOME=${jdk11}"
+  '';
+
+  passthru = {
+    tests.nifi = nixosTests.nifi;
+  };
+
+  meta = with lib; {
+    description = "Easy to use, powerful, and reliable system to process and distribute data";
+    longDescription = ''
+      Apache NiFi supports powerful and scalable directed graphs of data routing,
+      transformation, and system mediation logic.
+    '';
+    license = licenses.asl20;
+    homepage = "https://nifi.apache.org";
+    platforms = [ "x86_64-linux" ];
+    sourceProvenance = with sourceTypes; [ binaryBytecode ];
+    maintainers = with maintainers; [ izorkin ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/outline/default.nix b/nixpkgs/pkgs/servers/web-apps/outline/default.nix
new file mode 100644
index 000000000000..6464035db317
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/outline/default.nix
@@ -0,0 +1,84 @@
+{ stdenv
+, lib
+, fetchFromGitHub
+, fetchYarnDeps
+, makeWrapper
+, prefetch-yarn-deps
+, nodejs
+, yarn
+, nixosTests
+}:
+
+stdenv.mkDerivation rec {
+  pname = "outline";
+  version = "0.75.2";
+
+  src = fetchFromGitHub {
+    owner = "outline";
+    repo = "outline";
+    rev = "v${version}";
+    hash = "sha256-jK1jZ9NyBl3Dioh/7gXWx6XyyI6xJKt2a/XXzbhllZM=";
+  };
+
+  nativeBuildInputs = [ makeWrapper prefetch-yarn-deps ];
+  buildInputs = [ yarn nodejs ];
+
+  yarnOfflineCache = fetchYarnDeps {
+    yarnLock = "${src}/yarn.lock";
+    hash = "sha256-8CfaP5T/pf/xq1lOfdOW4n2m12QLnkLFynHABjZwNiY=";
+  };
+
+  configurePhase = ''
+    export HOME=$(mktemp -d)/yarn_home
+  '';
+
+  buildPhase = ''
+    runHook preBuild
+    export NODE_OPTIONS=--openssl-legacy-provider
+
+    yarn config --offline set yarn-offline-mirror $yarnOfflineCache
+    fixup-yarn-lock yarn.lock
+
+    yarn install --offline \
+      --frozen-lockfile \
+      --ignore-engines --ignore-scripts
+    patchShebangs node_modules/
+    # apply upstream patches with `patch-package`
+    yarn run postinstall
+    yarn build
+
+    runHook postBuild
+  '';
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir -p $out/bin $out/share/outline
+    mv build server public node_modules $out/share/outline/
+
+    node_modules=$out/share/outline/node_modules
+    build=$out/share/outline/build
+    server=$out/share/outline/server
+
+    makeWrapper ${nodejs}/bin/node $out/bin/outline-server \
+      --add-flags $build/server/index.js \
+      --set NODE_ENV production \
+      --set NODE_PATH $node_modules \
+      --prefix PATH : ${lib.makeBinPath [ nodejs ]} # required to run migrations
+
+    runHook postInstall
+  '';
+
+  passthru.tests = {
+    basic-functionality = nixosTests.outline;
+  };
+
+  meta = with lib; {
+    description = "The fastest wiki and knowledge base for growing teams. Beautiful, feature rich, and markdown compatible";
+    homepage = "https://www.getoutline.com/";
+    changelog = "https://github.com/outline/outline/releases";
+    license = licenses.bsl11;
+    maintainers = with maintainers; [ cab404 yrd xanderio ];
+    platforms = platforms.linux;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/peering-manager/default.nix b/nixpkgs/pkgs/servers/web-apps/peering-manager/default.nix
new file mode 100644
index 000000000000..aec18b2904c6
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/peering-manager/default.nix
@@ -0,0 +1,84 @@
+{ python3
+, fetchFromGitHub
+, fetchpatch
+, nixosTests
+, lib
+
+, plugins ? ps: []
+}:
+
+python3.pkgs.buildPythonApplication rec {
+  pname = "peering-manager";
+  version = "1.8.3";
+
+  src = fetchFromGitHub {
+    owner = pname;
+    repo = pname;
+    rev = "refs/tags/v${version}";
+    sha256 = "sha256-UV1zSX9C9y5faOBUQ7bfj2DT6ffhMW28MIT7SaYjMgw=";
+  };
+
+  format = "other";
+
+  propagatedBuildInputs = with python3.pkgs; [
+    django
+    djangorestframework
+    django-redis
+    django-debug-toolbar
+    django-filter
+    django-postgresql-netfields
+    django-prometheus
+    django-rq
+    django-tables2
+    django-taggit
+    drf-spectacular
+    drf-spectacular-sidecar
+    jinja2
+    markdown
+    napalm
+    packaging
+    psycopg2
+    pyixapi
+    pynetbox
+    pyyaml
+    requests
+    tzdata
+  ] ++ plugins python3.pkgs;
+
+  buildPhase = ''
+    runHook preBuild
+    cp peering_manager/configuration{.example,}.py
+    python3 manage.py collectstatic --no-input
+    rm -f peering_manager/configuration.py
+    runHook postBuild
+  '';
+
+  installPhase = ''
+    runHook preInstall
+    mkdir -p $out/opt/peering-manager
+    cp -r . $out/opt/peering-manager
+    chmod +x $out/opt/peering-manager/manage.py
+    makeWrapper $out/opt/peering-manager/manage.py $out/bin/peering-manager \
+      --prefix PYTHONPATH : "$PYTHONPATH"
+    runHook postInstall
+  '';
+
+  passthru = {
+    # PYTHONPATH of all dependencies used by the package
+    python = python3;
+    pythonPath = python3.pkgs.makePythonPath propagatedBuildInputs;
+
+    tests = {
+      inherit (nixosTests) peering-manager;
+    };
+  };
+
+  meta = with lib; {
+    homepage = "https://peering-manager.net/";
+    license = licenses.asl20;
+    description = "BGP sessions management tool";
+    mainProgram = "peering-manager";
+    maintainers = teams.wdz.members;
+    platforms = platforms.linux;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/pgpkeyserver-lite/default.nix b/nixpkgs/pkgs/servers/web-apps/pgpkeyserver-lite/default.nix
new file mode 100644
index 000000000000..4318f2d29a14
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/pgpkeyserver-lite/default.nix
@@ -0,0 +1,25 @@
+{ lib, stdenv, fetchFromGitHub }:
+
+stdenv.mkDerivation {
+  pname = "pgpkeyserver-lite";
+  version = "2017-07-18";
+
+  src = fetchFromGitHub {
+    owner = "mattrude";
+    repo = "pgpkeyserver-lite";
+    rev = "a038cb7";
+    sha256 = "12pn92pcpv38b2gmamppn9yzdn7x52pgxnzpal22gqsxwimhs2rx";
+  };
+
+  installPhase = ''
+    mkdir -p $out
+    cp -R 404.html assets favicon.ico index.html robots.txt $out
+  '';
+
+  meta = with lib; {
+    homepage = "https://github.com/mattrude/pgpkeyserver-lite";
+    description = "A lightweight static front-end for a sks keyserver";
+    license = licenses.gpl3;
+    maintainers = with maintainers; [ calbrecht ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/phylactery/default.nix b/nixpkgs/pkgs/servers/web-apps/phylactery/default.nix
new file mode 100644
index 000000000000..2dfccdabbb98
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/phylactery/default.nix
@@ -0,0 +1,32 @@
+{ lib, buildGoModule, fetchFromSourcehut, nixosTests }:
+
+buildGoModule rec {
+  pname = "phylactery";
+  version = "0.1.2";
+
+  src = fetchFromSourcehut {
+    owner = "~cnx";
+    repo = pname;
+    rev = version;
+    hash = "sha256-HQN6wJ/4YeuQaDcNgdHj0RgYnn2NxXGRfxybmv60EdQ=";
+  };
+
+  vendorHash = null;
+
+  preBuild = ''
+    cp ${./go.mod} go.mod
+  '';
+
+  ldflags = [ "-s" "-w" ];
+
+  passthru.tests.phylactery = nixosTests.phylactery;
+
+  meta = with lib; {
+    description = "Old school comic web server";
+    mainProgram = "phylactery";
+    homepage = "https://git.sr.ht/~cnx/phylactery";
+    license = licenses.agpl3Plus;
+    maintainers = with maintainers; [ McSinyx ];
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/phylactery/go.mod b/nixpkgs/pkgs/servers/web-apps/phylactery/go.mod
new file mode 100644
index 000000000000..4ec9652e23fe
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/phylactery/go.mod
@@ -0,0 +1,3 @@
+module git.sr.ht/~cnx/phylactery
+
+go 1.18
diff --git a/nixpkgs/pkgs/servers/web-apps/pict-rs/0.3.nix b/nixpkgs/pkgs/servers/web-apps/pict-rs/0.3.nix
new file mode 100644
index 000000000000..875aecd55610
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/pict-rs/0.3.nix
@@ -0,0 +1,54 @@
+{ stdenv
+, lib
+, fetchFromGitea
+, rustPlatform
+, makeWrapper
+, protobuf
+, Security
+, imagemagick
+, ffmpeg
+, exiftool
+, nixosTests
+}:
+
+rustPlatform.buildRustPackage rec {
+  pname = "pict-rs";
+  version = "0.3.3";
+
+  src = fetchFromGitea {
+    domain = "git.asonix.dog";
+    owner = "asonix";
+    repo = pname;
+    rev = "v${version}";
+    sha256 = "mEZBFDR+/aMRFw54Yq+f1gyEz8H+5IggNCpzv3UdDFg=";
+  };
+
+  cargoLock = {
+    lockFile = ./Cargo-0.3.lock;
+    outputHashes = {
+      "aws-creds-0.29.1" = "bwDFmDPThMLrpaB7cAj/2/vJKhbX6/DqgcIRBVKSZhg=";
+    };
+  };
+
+  # needed for internal protobuf c wrapper library
+  PROTOC = "${protobuf}/bin/protoc";
+  PROTOC_INCLUDE = "${protobuf}/include";
+
+  nativeBuildInputs = [ makeWrapper ];
+  buildInputs = lib.optionals stdenv.isDarwin [ Security ];
+
+  postInstall = ''
+    wrapProgram "$out/bin/pict-rs" \
+        --prefix PATH : "${lib.makeBinPath [ imagemagick ffmpeg exiftool ]}"
+  '';
+
+  passthru.tests = { inherit (nixosTests) pict-rs; };
+
+  meta = with lib; {
+    description = "A simple image hosting service";
+    mainProgram = "pict-rs";
+    homepage = "https://git.asonix.dog/asonix/pict-rs";
+    license = with licenses; [ agpl3Plus ];
+    maintainers = with maintainers; [ happysalada ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/pict-rs/Cargo-0.3.lock b/nixpkgs/pkgs/servers/web-apps/pict-rs/Cargo-0.3.lock
new file mode 100644
index 000000000000..c5618b62d420
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/pict-rs/Cargo-0.3.lock
@@ -0,0 +1,3105 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "actix-codec"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe"
+dependencies = [
+ "bitflags",
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "memchr",
+ "pin-project-lite",
+ "tokio",
+ "tokio-util",
+]
+
+[[package]]
+name = "actix-form-data"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd2788a4c359a372371292ef9903cf26759abf3ddf00ed710061808b1414fc75"
+dependencies = [
+ "actix-multipart",
+ "actix-rt",
+ "actix-web",
+ "futures-util",
+ "mime",
+ "thiserror",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "actix-http"
+version = "3.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2079246596c18b4a33e274ae10c0e50613f4d32a4198e09c7b93771013fed74"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "ahash 0.8.3",
+ "base64 0.21.0",
+ "bitflags",
+ "bytes",
+ "bytestring",
+ "derive_more",
+ "encoding_rs",
+ "futures-core",
+ "h2",
+ "http",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "language-tags",
+ "local-channel",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rand",
+ "sha1",
+ "smallvec",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "actix-macros"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6"
+dependencies = [
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "actix-multipart"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9edfb0e7663d7fe18c8d5b668c9c1bcf79176b1dcc9d4da9592503209a6bfb0"
+dependencies = [
+ "actix-utils",
+ "actix-web",
+ "bytes",
+ "derive_more",
+ "futures-core",
+ "httparse",
+ "local-waker",
+ "log",
+ "mime",
+ "twoway",
+]
+
+[[package]]
+name = "actix-router"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799"
+dependencies = [
+ "bytestring",
+ "http",
+ "regex",
+ "serde",
+ "tracing",
+]
+
+[[package]]
+name = "actix-rt"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e"
+dependencies = [
+ "actix-macros",
+ "futures-core",
+ "tokio",
+ "tokio-uring",
+]
+
+[[package]]
+name = "actix-server"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e8613a75dd50cc45f473cee3c34d59ed677c0f7b44480ce3b8247d7dc519327"
+dependencies = [
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "futures-core",
+ "futures-util",
+ "mio",
+ "num_cpus",
+ "socket2",
+ "tokio",
+ "tokio-uring",
+ "tracing",
+]
+
+[[package]]
+name = "actix-service"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a"
+dependencies = [
+ "futures-core",
+ "paste",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "actix-tls"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fde0cf292f7cdc7f070803cb9a0d45c018441321a78b1042ffbbb81ec333297"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "futures-core",
+ "http",
+ "log",
+ "pin-project-lite",
+ "tokio-rustls",
+ "tokio-util",
+ "webpki-roots",
+]
+
+[[package]]
+name = "actix-utils"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8"
+dependencies = [
+ "local-waker",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "actix-web"
+version = "4.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd3cb42f9566ab176e1ef0b8b3a896529062b4efc6be0123046095914c4c1c96"
+dependencies = [
+ "actix-codec",
+ "actix-http",
+ "actix-router",
+ "actix-rt",
+ "actix-server",
+ "actix-service",
+ "actix-utils",
+ "ahash 0.7.6",
+ "bytes",
+ "bytestring",
+ "cfg-if",
+ "derive_more",
+ "encoding_rs",
+ "futures-core",
+ "futures-util",
+ "http",
+ "itoa",
+ "language-tags",
+ "log",
+ "mime",
+ "once_cell",
+ "pin-project-lite",
+ "regex",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "smallvec",
+ "socket2",
+ "time",
+ "url",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "ahash"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+dependencies = [
+ "getrandom",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "ahash"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
+dependencies = [
+ "cfg-if",
+ "getrandom",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+
+[[package]]
+name = "async-stream"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi 0.1.19",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "awc"
+version = "3.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87ef547a81796eb2dfe9b345aba34c2e08391a0502493711395b36dd64052b69"
+dependencies = [
+ "actix-codec",
+ "actix-http",
+ "actix-rt",
+ "actix-service",
+ "actix-tls",
+ "actix-utils",
+ "ahash 0.7.6",
+ "base64 0.21.0",
+ "bytes",
+ "cfg-if",
+ "derive_more",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "itoa",
+ "log",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rand",
+ "rustls",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "tokio",
+]
+
+[[package]]
+name = "aws-creds"
+version = "0.29.1"
+source = "git+https://github.com/asonix/rust-s3?branch=asonix/generic-client#9e450d0038a29040ba5c47ffa570350c3b1ad976"
+dependencies = [
+ "dirs",
+ "rust-ini",
+ "serde",
+ "serde-xml-rs",
+ "serde_derive",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "aws-region"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bdd1c0f4aa70f72812a2f3ec325d6d6162fb80cff093f847b4c394fd78c3643"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
+name = "axum"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39"
+dependencies = [
+ "async-trait",
+ "axum-core",
+ "bitflags",
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "hyper",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustversion",
+ "serde",
+ "sync_wrapper",
+ "tower",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "axum-core"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
+dependencies = [
+ "async-trait",
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "mime",
+ "rustversion",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
+[[package]]
+name = "base64"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "bytes"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+
+[[package]]
+name = "bytestring"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "238e4886760d98c4f899360c834fa93e62cf7f721ac3c2da375cbdf4b8679aae"
+dependencies = [
+ "bytes",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "2.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "config"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7"
+dependencies = [
+ "async-trait",
+ "json5",
+ "lazy_static",
+ "nom",
+ "pathdiff",
+ "ron",
+ "rust-ini",
+ "serde",
+ "serde_json",
+ "toml",
+ "yaml-rust",
+]
+
+[[package]]
+name = "console-api"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e57ff02e8ad8e06ab9731d5dc72dc23bef9200778eae1a89d555d8c42e5d4a86"
+dependencies = [
+ "prost",
+ "prost-types",
+ "tonic",
+ "tracing-core",
+]
+
+[[package]]
+name = "console-subscriber"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22a3a81dfaf6b66bce5d159eddae701e3a002f194d378cbf7be5f053c281d9be"
+dependencies = [
+ "console-api",
+ "crossbeam-channel",
+ "crossbeam-utils",
+ "futures",
+ "hdrhistogram",
+ "humantime",
+ "prost-types",
+ "serde",
+ "serde_json",
+ "thread_local",
+ "tokio",
+ "tokio-stream",
+ "tonic",
+ "tracing",
+ "tracing-core",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "convert_case"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "dashmap"
+version = "5.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc"
+dependencies = [
+ "cfg-if",
+ "hashbrown",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core 0.9.7",
+]
+
+[[package]]
+name = "derive_more"
+version = "0.99.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
+dependencies = [
+ "convert_case",
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "dirs"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
+name = "dlv-list"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
+
+[[package]]
+name = "either"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+
+[[package]]
+name = "encoding_rs"
+version = "0.8.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "flate2"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "fs2"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "futures"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
+
+[[package]]
+name = "futures-task"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
+
+[[package]]
+name = "futures-util"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "fxhash"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "h2"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+dependencies = [
+ "ahash 0.7.6",
+]
+
+[[package]]
+name = "hdrhistogram"
+version = "7.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8"
+dependencies = [
+ "base64 0.13.1",
+ "byteorder",
+ "flate2",
+ "nom",
+ "num-traits",
+]
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "http"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+
+[[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "hyper"
+version = "0.14.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-rustls"
+version = "0.23.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c"
+dependencies = [
+ "http",
+ "hyper",
+ "rustls",
+ "tokio",
+ "tokio-rustls",
+]
+
+[[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
+name = "idna"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "io-uring"
+version = "0.5.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd1e1a01cfb924fd8c5c43b6827965db394f5a3a16c599ce03452266e1cf984c"
+dependencies = [
+ "bitflags",
+ "libc",
+]
+
+[[package]]
+name = "ipnet"
+version = "2.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+
+[[package]]
+name = "js-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "json5"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"
+dependencies = [
+ "pest",
+ "pest_derive",
+ "serde",
+]
+
+[[package]]
+name = "language-tags"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.144"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
+
+[[package]]
+name = "local-channel"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "local-waker",
+]
+
+[[package]]
+name = "local-waker"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1"
+
+[[package]]
+name = "lock_api"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "matchers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata",
+]
+
+[[package]]
+name = "matchit"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
+
+[[package]]
+name = "maybe-async"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "md5"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "memoffset"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+dependencies = [
+ "hermit-abi 0.2.6",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+
+[[package]]
+name = "opentelemetry"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69d6c3d7288a106c0a363e4b0e8d308058d56902adefb16f4936f417ffef086e"
+dependencies = [
+ "opentelemetry_api",
+ "opentelemetry_sdk",
+]
+
+[[package]]
+name = "opentelemetry-otlp"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1c928609d087790fc936a1067bdc310ae702bdf3b090c3f281b713622c8bbde"
+dependencies = [
+ "async-trait",
+ "futures",
+ "futures-util",
+ "http",
+ "opentelemetry",
+ "opentelemetry-proto",
+ "prost",
+ "thiserror",
+ "tokio",
+ "tonic",
+]
+
+[[package]]
+name = "opentelemetry-proto"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d61a2f56df5574508dd86aaca016c917489e589ece4141df1b5e349af8d66c28"
+dependencies = [
+ "futures",
+ "futures-util",
+ "opentelemetry",
+ "prost",
+ "tonic",
+ "tonic-build",
+]
+
+[[package]]
+name = "opentelemetry_api"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c24f96e21e7acc813c7a8394ee94978929db2bcc46cf6b5014fc612bf7760c22"
+dependencies = [
+ "fnv",
+ "futures-channel",
+ "futures-util",
+ "indexmap",
+ "js-sys",
+ "once_cell",
+ "pin-project-lite",
+ "thiserror",
+]
+
+[[package]]
+name = "opentelemetry_sdk"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ca41c4933371b61c2a2f214bf16931499af4ec90543604ec828f7a625c09113"
+dependencies = [
+ "async-trait",
+ "crossbeam-channel",
+ "dashmap",
+ "fnv",
+ "futures-channel",
+ "futures-executor",
+ "futures-util",
+ "once_cell",
+ "opentelemetry_api",
+ "percent-encoding",
+ "rand",
+ "thiserror",
+ "tokio",
+ "tokio-stream",
+]
+
+[[package]]
+name = "ordered-multimap"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a"
+dependencies = [
+ "dlv-list",
+ "hashbrown",
+]
+
+[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core 0.8.6",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core 0.9.7",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall 0.2.16",
+ "smallvec",
+ "winapi",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.2.16",
+ "smallvec",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
+
+[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
+name = "percent-encoding"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+
+[[package]]
+name = "pest"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70"
+dependencies = [
+ "thiserror",
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411"
+dependencies = [
+ "once_cell",
+ "pest",
+ "sha2",
+]
+
+[[package]]
+name = "petgraph"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "pict-rs"
+version = "0.3.3"
+dependencies = [
+ "actix-form-data",
+ "actix-rt",
+ "actix-server",
+ "actix-web",
+ "anyhow",
+ "async-trait",
+ "awc",
+ "base64 0.21.0",
+ "config",
+ "console-subscriber",
+ "dashmap",
+ "futures-util",
+ "mime",
+ "num_cpus",
+ "once_cell",
+ "opentelemetry",
+ "opentelemetry-otlp",
+ "pin-project-lite",
+ "reqwest",
+ "rust-s3",
+ "serde",
+ "serde_json",
+ "sha2",
+ "sled",
+ "storage-path-generator",
+ "structopt",
+ "thiserror",
+ "time",
+ "tokio",
+ "tokio-uring",
+ "tokio-util",
+ "tracing",
+ "tracing-actix-web",
+ "tracing-awc",
+ "tracing-error",
+ "tracing-futures",
+ "tracing-log",
+ "tracing-opentelemetry",
+ "tracing-subscriber",
+ "url",
+ "uuid",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "prettyplease"
+version = "0.1.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
+dependencies = [
+ "proc-macro2",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "prost"
+version = "0.11.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd"
+dependencies = [
+ "bytes",
+ "prost-derive",
+]
+
+[[package]]
+name = "prost-build"
+version = "0.11.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270"
+dependencies = [
+ "bytes",
+ "heck 0.4.1",
+ "itertools",
+ "lazy_static",
+ "log",
+ "multimap",
+ "petgraph",
+ "prettyplease",
+ "prost",
+ "prost-types",
+ "regex",
+ "syn 1.0.109",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.11.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
+dependencies = [
+ "anyhow",
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.11.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13"
+dependencies = [
+ "prost",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall 0.2.16",
+ "thiserror",
+]
+
+[[package]]
+name = "regex"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.7.1",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax 0.6.29",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+
+[[package]]
+name = "regex-syntax"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
+
+[[package]]
+name = "reqwest"
+version = "0.11.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91"
+dependencies = [
+ "base64 0.21.0",
+ "bytes",
+ "encoding_rs",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-rustls",
+ "ipnet",
+ "js-sys",
+ "log",
+ "mime",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustls",
+ "rustls-pemfile",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "tokio",
+ "tokio-rustls",
+ "tokio-util",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "wasm-streams",
+ "web-sys",
+ "webpki-roots",
+ "winreg",
+]
+
+[[package]]
+name = "ring"
+version = "0.16.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin",
+ "untrusted",
+ "web-sys",
+ "winapi",
+]
+
+[[package]]
+name = "rio"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e98c25665909853c07874301124482754434520ab572ac6a22e90366de6685b"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "ron"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
+dependencies = [
+ "base64 0.13.1",
+ "bitflags",
+ "serde",
+]
+
+[[package]]
+name = "rust-ini"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df"
+dependencies = [
+ "cfg-if",
+ "ordered-multimap",
+]
+
+[[package]]
+name = "rust-s3"
+version = "0.31.0"
+source = "git+https://github.com/asonix/rust-s3?branch=asonix/generic-client#9e450d0038a29040ba5c47ffa570350c3b1ad976"
+dependencies = [
+ "async-trait",
+ "aws-creds",
+ "aws-region",
+ "base64 0.13.1",
+ "cfg-if",
+ "hex",
+ "hmac",
+ "http",
+ "log",
+ "maybe-async",
+ "md5",
+ "percent-encoding",
+ "reqwest",
+ "serde",
+ "serde-xml-rs",
+ "serde_derive",
+ "sha2",
+ "thiserror",
+ "time",
+ "tokio",
+ "tokio-stream",
+ "url",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustix"
+version = "0.37.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "rustls"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
+dependencies = [
+ "log",
+ "ring",
+ "sct",
+ "webpki",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
+dependencies = [
+ "base64 0.21.0",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
+
+[[package]]
+name = "ryu"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+
+[[package]]
+name = "scoped-tls"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "sct"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
+
+[[package]]
+name = "serde"
+version = "1.0.162"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde-xml-rs"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65162e9059be2f6a3421ebbb4fef3e74b7d9e7c60c50a0e292c6239f19f1edfa"
+dependencies = [
+ "log",
+ "serde",
+ "thiserror",
+ "xml-rs",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.162"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.96"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha1"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sharded-slab"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "sled"
+version = "0.34.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935"
+dependencies = [
+ "crc32fast",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+ "fs2",
+ "fxhash",
+ "libc",
+ "log",
+ "parking_lot 0.11.2",
+ "rio",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "socket2"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
+name = "storage-path-generator"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f11d35dae9818c4313649da4a97c8329e29357a7fe584526c1d78f5b63ef836"
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "structopt"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
+dependencies = [
+ "clap",
+ "lazy_static",
+ "structopt-derive",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
+dependencies = [
+ "heck 0.3.3",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "sync_wrapper"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+
+[[package]]
+name = "tempfile"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "redox_syscall 0.3.5",
+ "rustix",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+]
+
+[[package]]
+name = "time"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
+dependencies = [
+ "itoa",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
+
+[[package]]
+name = "time-macros"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
+dependencies = [
+ "time-core",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "tokio"
+version = "1.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
+dependencies = [
+ "autocfg",
+ "bytes",
+ "libc",
+ "mio",
+ "num_cpus",
+ "parking_lot 0.12.1",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "tracing",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "tokio-io-timeout"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "tokio-rustls"
+version = "0.23.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
+dependencies = [
+ "rustls",
+ "tokio",
+ "webpki",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-uring"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d5e02bb137e030b3a547c65a3bd2f1836d66a97369fdcc69034002b10e155ef"
+dependencies = [
+ "bytes",
+ "io-uring",
+ "libc",
+ "scoped-tls",
+ "slab",
+ "socket2",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "tonic"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "axum",
+ "base64 0.13.1",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tokio-stream",
+ "tokio-util",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4"
+dependencies = [
+ "prettyplease",
+ "proc-macro2",
+ "prost-build",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+dependencies = [
+ "cfg-if",
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-actix-web"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2def0ffabc0116481e14e82cf705fef814f5178171d445b6790137ff8a85a73"
+dependencies = [
+ "actix-web",
+ "opentelemetry",
+ "pin-project",
+ "tracing",
+ "tracing-opentelemetry",
+ "uuid",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "tracing-awc"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab0b57d9e4b25f3d5f17d705c11c13c333b26dc062c02a9dedfe6a26f750a99e"
+dependencies = [
+ "actix-http",
+ "actix-service",
+ "awc",
+ "bytes",
+ "futures-core",
+ "opentelemetry",
+ "pin-project-lite",
+ "tracing",
+ "tracing-opentelemetry",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
+dependencies = [
+ "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-error"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
+dependencies = [
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
+dependencies = [
+ "lazy_static",
+ "log",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-opentelemetry"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21ebb87a95ea13271332df069020513ab70bdb5637ca42d6e492dc3bbbad48de"
+dependencies = [
+ "once_cell",
+ "opentelemetry",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
+
+[[package]]
+name = "twoway"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c57ffb460d7c24cd6eda43694110189030a3d1dfe418416d9468fd1c1d290b47"
+dependencies = [
+ "memchr",
+ "unchecked-index",
+]
+
+[[package]]
+name = "typenum"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
+
+[[package]]
+name = "unchecked-index"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
+[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
+[[package]]
+name = "url"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+ "serde",
+]
+
+[[package]]
+name = "uuid"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2"
+dependencies = [
+ "getrandom",
+ "serde",
+]
+
+[[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+
+[[package]]
+name = "wasm-streams"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078"
+dependencies = [
+ "futures-util",
+ "js-sys",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webpki"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "0.22.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
+dependencies = [
+ "webpki",
+]
+
+[[package]]
+name = "which"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
+dependencies = [
+ "either",
+ "libc",
+ "once_cell",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
+[[package]]
+name = "winreg"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "xml-rs"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "699d0104bcdd7e7af6d093d6c6e2d0c479b8a129ee0d1023b31d2e0c71bfdda2"
+
+[[package]]
+name = "yaml-rust"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+dependencies = [
+ "linked-hash-map",
+]
diff --git a/nixpkgs/pkgs/servers/web-apps/pict-rs/default.nix b/nixpkgs/pkgs/servers/web-apps/pict-rs/default.nix
new file mode 100644
index 000000000000..fdd975e3682c
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/pict-rs/default.nix
@@ -0,0 +1,50 @@
+{ stdenv
+, lib
+, fetchFromGitea
+, rustPlatform
+, makeWrapper
+, protobuf
+, darwin
+, imagemagick
+, ffmpeg
+, exiftool
+, nixosTests
+}:
+
+rustPlatform.buildRustPackage rec {
+  pname = "pict-rs";
+  version = "0.5.9";
+
+  src = fetchFromGitea {
+    domain = "git.asonix.dog";
+    owner = "asonix";
+    repo = pname;
+    rev = "v${version}";
+    sha256 = "sha256-ZRT382ClImnlwvWyA1w7ZIIF4PXr3rWmeIsqJYngkfM=";
+  };
+
+  cargoHash = "sha256-FTb8VoQJFS55CKlQvoWkBQEBUCvUnFaUAxIW22zEIHI=";
+
+  # needed for internal protobuf c wrapper library
+  PROTOC = "${protobuf}/bin/protoc";
+  PROTOC_INCLUDE = "${protobuf}/include";
+
+  nativeBuildInputs = [ makeWrapper ];
+  buildInputs = lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
+
+  postInstall = ''
+    wrapProgram "$out/bin/pict-rs" \
+        --prefix PATH : "${lib.makeBinPath [ imagemagick ffmpeg exiftool ]}"
+  '';
+
+  passthru.tests = { inherit (nixosTests) pict-rs; };
+
+  meta = with lib; {
+    broken = stdenv.isDarwin;
+    description = "A simple image hosting service";
+    mainProgram = "pict-rs";
+    homepage = "https://git.asonix.dog/asonix/pict-rs";
+    license = with licenses; [ agpl3Plus ];
+    maintainers = with maintainers; [ happysalada ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/pixelfed/default.nix b/nixpkgs/pkgs/servers/web-apps/pixelfed/default.nix
new file mode 100644
index 000000000000..2b1f2e730206
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/pixelfed/default.nix
@@ -0,0 +1,49 @@
+{ lib
+, stdenv
+, fetchFromGitHub
+, php
+, nixosTests
+, nix-update-script
+, dataDir ? "/var/lib/pixelfed"
+, runtimeDir ? "/run/pixelfed"
+}:
+
+php.buildComposerProject (finalAttrs: {
+  pname = "pixelfed";
+  version = "0.11.13";
+
+  src = fetchFromGitHub {
+    owner = "pixelfed";
+    repo = finalAttrs.pname;
+    rev = "v${finalAttrs.version}";
+    hash = "sha256-bEwKaC9fSOGLQbjsuPuIdMMbO3kzvzQxWQR8C2A4mQc=";
+  };
+
+  vendorHash = "sha256-ahQsOq3qOMGt3b0Ebac4xex+MP9knTmjyCy0PSNE4W8=";
+
+  postInstall = ''
+    mv "$out/share/php/${finalAttrs.pname}"/* $out
+    rm -R $out/bootstrap/cache
+    # Move static contents for the NixOS module to pick it up, if needed.
+    mv $out/bootstrap $out/bootstrap-static
+    mv $out/storage $out/storage-static
+    ln -s ${dataDir}/.env $out/.env
+    ln -s ${dataDir}/storage $out/
+    ln -s ${dataDir}/storage/app/public $out/public/storage
+    ln -s ${runtimeDir} $out/bootstrap
+    chmod +x $out/artisan
+  '';
+
+  passthru = {
+    tests = { inherit (nixosTests) pixelfed; };
+    updateScript = nix-update-script { };
+  };
+
+  meta = with lib; {
+    description = "A federated image sharing platform";
+    license = licenses.agpl3Only;
+    homepage = "https://pixelfed.org/";
+    maintainers = with maintainers; [ raitobezarius ];
+    platforms = php.meta.platforms;
+  };
+})
diff --git a/nixpkgs/pkgs/servers/web-apps/plausible/default.nix b/nixpkgs/pkgs/servers/web-apps/plausible/default.nix
new file mode 100644
index 000000000000..24f684c0c954
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/plausible/default.nix
@@ -0,0 +1,95 @@
+{ lib
+, beamPackages
+, buildNpmPackage
+, fetchFromGitHub
+, nodejs
+, nixosTests
+, ...
+}:
+
+let
+  pname = "plausible";
+  version = "2.0.0";
+
+  src = fetchFromGitHub {
+    owner = "plausible";
+    repo = "analytics";
+    rev = "v${version}";
+    hash = "sha256-yrTwxBguAZbfEKucUL+w49Hr6D7v9/2OjY1h27+w5WI=";
+  };
+
+  # TODO consider using `mix2nix` as soon as it supports git dependencies.
+  mixFodDeps = beamPackages.fetchMixDeps {
+    pname = "${pname}-deps";
+    inherit src version;
+    hash = "sha256-CAyZLpjmw1JreK3MopqI0XsWhP+fJEMpXlww7CibSaM=";
+  };
+
+  assets = buildNpmPackage {
+    pname = "${pname}-assets";
+    inherit version;
+    src = "${src}/assets";
+    npmDepsHash = "sha256-2t1M6RQhBjZxx36qawVUVC+ob9SvQIq5dy4HgVeY2Eo=";
+    dontNpmBuild = true;
+    installPhase = ''
+      runHook preInstall
+      cp -r . "$out"
+      runHook postInstall
+    '';
+  };
+
+  tracker = buildNpmPackage {
+    pname = "${pname}-tracker";
+    inherit version;
+    src = "${src}/tracker";
+    npmDepsHash = "sha256-y09jVSwUrxF0nLpLqS1yQweYL+iMF6jVx0sUdQtvrpc=";
+    dontNpmBuild = true;
+    installPhase = ''
+      runHook preInstall
+      cp -r . "$out"
+      runHook postInstall
+    '';
+  };
+in
+beamPackages.mixRelease {
+  inherit pname version src mixFodDeps;
+
+  nativeBuildInputs = [
+    nodejs
+  ];
+
+  passthru = {
+    tests = { inherit (nixosTests) plausible; };
+    updateScript = ./update.sh;
+  };
+
+  postPatch = ''
+    substituteInPlace lib/plausible_release.ex --replace 'defp prepare do' 'def prepare do'
+  '';
+
+  preBuild = ''
+    rm -r assets tracker
+    cp -r ${assets} assets
+    cp -r ${tracker} tracker
+  '';
+
+  postBuild = ''
+    export NODE_OPTIONS=--openssl-legacy-provider # required for webpack compatibility with OpenSSL 3 (https://github.com/webpack/webpack/issues/14532)
+    npm run deploy --prefix ./assets
+    npm run deploy --prefix ./tracker
+
+    # for external task you need a workaround for the no deps check flag
+    # https://github.com/phoenixframework/phoenix/issues/2690
+    mix do deps.loadpaths --no-deps-check, phx.digest
+  '';
+
+  meta = with lib; {
+    license = licenses.agpl3Plus;
+    homepage = "https://plausible.io/";
+    changelog = "https://github.com/plausible/analytics/blob/${src.rev}/CHANGELOG.md";
+    description = " Simple, open-source, lightweight (< 1 KB) and privacy-friendly web analytics alternative to Google Analytics";
+    mainProgram = "plausible";
+    maintainers = with maintainers; [ ];
+    platforms = platforms.unix;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/plausible/update.sh b/nixpkgs/pkgs/servers/web-apps/plausible/update.sh
new file mode 100755
index 000000000000..8ed285cfcb88
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/plausible/update.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env nix-shell
+#!nix-shell -i bash -p jq nix-prefetch-github yarn yarn2nix-moretea.yarn2nix moreutils
+
+# NOTE: please check on new releases which steps aren't necessary anymore!
+# Currently the following things are done:
+#
+# * Add correct `name`/`version` field to `package.json`, otherwise `yarn2nix` fails to
+#   find required dependencies.
+# * Adjust `file:`-dependencies a bit for the structure inside a Nix build.
+# * Update hashes for the tarball & the fixed-output drv with all `mix`-dependencies.
+# * Generate `yarn.lock` & `yarn.nix` in a temporary directory.
+
+set -euxo pipefail
+
+dir="$(realpath $(dirname "$0"))"
+export latest="$(curl -q https://api.github.com/repos/plausible/analytics/releases/latest \
+  | jq -r '.tag_name')"
+nix_version="$(cut -c2- <<< "$latest")"
+
+if [[ "$(nix-instantiate -A plausible.version --eval --json | jq -r)" = "$nix_version" ]];
+then
+  echo "Already using version $latest, skipping"
+  exit 0
+fi
+
+SRC="https://raw.githubusercontent.com/plausible/analytics/${latest}"
+
+package_json="$(curl -qf "$SRC/assets/package.json")"
+
+echo "$package_json" \
+  | jq '. + {"name":"plausible","version": $ENV.latest}' \
+  | sed -e 's,../deps/,../../tmp/deps/,g' \
+  > $dir/package.json
+
+tarball_meta="$(nix-prefetch-github plausible analytics --rev "$latest")"
+tarball_hash="$(jq -r '.hash' <<< "$tarball_meta")"
+tarball_path="$(nix-build -E 'with import ./. {}; { p }: fetchFromGitHub (builtins.fromJSON p)' --argstr p "$tarball_meta")"
+fake_hash="$(nix-instantiate --eval -A lib.fakeHash | xargs echo)"
+
+sed -i "$dir/default.nix" \
+  -e 's,version = ".*",version = "'"$nix_version"'",' \
+  -e '/^  src = fetchFromGitHub/,+4{;s#hash = "\(.*\)"#hash = "'"$tarball_hash"'"#}' \
+  -e '/^  mixFodDeps =/,+3{;s#hash = "\(.*\)"#hash = "'"$fake_hash"'"#}'
+
+mix_hash="$(nix-build -A plausible.mixFodDeps 2>&1 | tail -n3 | grep 'got:' | cut -d: -f2- | xargs echo || true)"
+
+sed -i "$dir/default.nix" -e '/^  mixFodDeps =/,+3{;s#hash = "\(.*\)"#hash = "'"$mix_hash"'"#}'
+
+tmp_setup_dir="$(mktemp -d)"
+trap "rm -rf $tmp_setup_dir" EXIT
+
+cp -r $tarball_path/* $tmp_setup_dir/
+cp -r "$(nix-build -A plausible.mixFodDeps)" "$tmp_setup_dir/deps"
+chmod -R u+rwx "$tmp_setup_dir"
+
+pushd $tmp_setup_dir/assets
+yarn
+yarn2nix > "$dir/yarn.nix"
+cp yarn.lock "$dir/yarn.lock"
+popd
+
+nix-build -A plausible
diff --git a/nixpkgs/pkgs/servers/web-apps/rss-bridge/default.nix b/nixpkgs/pkgs/servers/web-apps/rss-bridge/default.nix
new file mode 100644
index 000000000000..e3936244e08b
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/rss-bridge/default.nix
@@ -0,0 +1,30 @@
+{ stdenv, lib, fetchFromGitHub }:
+
+stdenv.mkDerivation rec {
+  pname = "rss-bridge";
+  version = "2024-02-02";
+
+  src = fetchFromGitHub {
+    owner = "RSS-Bridge";
+    repo = "rss-bridge";
+    rev = version;
+    sha256 = "sha256-VycEgu7uHYwDnNE1eoVxgaWZAnC6mZLBxT8Le3PI4Rs=";
+  };
+
+  patches = [
+    ./paths.patch
+  ];
+
+  installPhase = ''
+    mkdir $out/
+    cp -R ./* $out
+  '';
+
+  meta = with lib; {
+    description = "The RSS feed for websites missing it";
+    homepage = "https://github.com/RSS-Bridge/rss-bridge";
+    license = licenses.unlicense;
+    maintainers = with maintainers; [ dawidsowa mynacol ];
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/rss-bridge/paths.patch b/nixpkgs/pkgs/servers/web-apps/rss-bridge/paths.patch
new file mode 100644
index 000000000000..21747a381bd6
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/rss-bridge/paths.patch
@@ -0,0 +1,38 @@
+diff --git a/lib/Configuration.php b/lib/Configuration.php
+index 63f67a3c..f0a53a24 100644
+--- a/lib/Configuration.php
++++ b/lib/Configuration.php
+@@ -81,8 +81,8 @@ public static function loadConfiguration(array $customConfig = [], array $env =
+             }
+         }
+ 
+-        if (file_exists(__DIR__ . '/../whitelist.txt')) {
+-            $enabledBridges = trim(file_get_contents(__DIR__ . '/../whitelist.txt'));
++        if (file_exists(getenv('RSSBRIDGE_DATA') . '/whitelist.txt')) {
++            $enabledBridges = trim(file_get_contents(getenv('RSSBRIDGE_DATA') . '/whitelist.txt'));
+             if ($enabledBridges === '*') {
+                 self::setConfig('system', 'enabled_bridges', ['*']);
+             } else {
+diff --git a/lib/bootstrap.php b/lib/bootstrap.php
+index 6465f5f9..4605596f 100644
+--- a/lib/bootstrap.php
++++ b/lib/bootstrap.php
+@@ -1,7 +1,7 @@
+ <?php
+ 
+ const PATH_LIB_CACHES = __DIR__ . '/../caches/';
+-const PATH_CACHE = __DIR__ . '/../cache/';
++define('PATH_CACHE', getenv('RSSBRIDGE_DATA') . '/cache/');
+ 
+ // Allow larger files for simple_html_dom
+ // todo: extract to config (if possible)
+@@ -43,7 +43,7 @@
+ });
+ 
+ $customConfig = [];
+-if (file_exists(__DIR__ . '/../config.ini.php')) {
+-    $customConfig = parse_ini_file(__DIR__ . '/../config.ini.php', true, INI_SCANNER_TYPED);
++if (file_exists(getenv('RSSBRIDGE_DATA') . '/config.ini.php')) {
++    $customConfig = parse_ini_file(getenv('RSSBRIDGE_DATA') . '/config.ini.php', true, INI_SCANNER_TYPED);
+ }
+ Configuration::loadConfiguration($customConfig, getenv());
diff --git a/nixpkgs/pkgs/servers/web-apps/selfoss/default.nix b/nixpkgs/pkgs/servers/web-apps/selfoss/default.nix
new file mode 100644
index 000000000000..b0b888012f46
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/selfoss/default.nix
@@ -0,0 +1,36 @@
+{ lib, stdenvNoCC, fetchurl, unzip }:
+
+stdenvNoCC.mkDerivation rec {
+  pname = "selfoss";
+  version = "2.19";
+
+  src = fetchurl {
+    url = "https://github.com/SSilence/selfoss/releases/download/${version}/selfoss-${version}.zip";
+    sha256 = "5JxHUOlyMneWPKaZtgLwn5FI4rnyWPzmsUQpSYrw5Pw=";
+  };
+
+  nativeBuildInputs = [
+    unzip
+  ];
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir "$out"
+    cp -ra \
+      .htaccess \
+      .nginx.conf \
+      * \
+      "$out/"
+
+    runHook postInstall
+  '';
+
+  meta = with lib; {
+    description = "Web-based news feed (RSS/Atom) aggregator";
+    homepage = "https://selfoss.aditu.de";
+    license = licenses.gpl3Only;
+    maintainers = with maintainers; [ jtojnar regnat ];
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/shaarli/default.nix b/nixpkgs/pkgs/servers/web-apps/shaarli/default.nix
new file mode 100644
index 000000000000..919daa61e198
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/shaarli/default.nix
@@ -0,0 +1,61 @@
+{ lib, stdenv, fetchurl }:
+
+stdenv.mkDerivation rec {
+  pname = "shaarli";
+  version = "0.13.0";
+
+  src = fetchurl {
+    url = "https://github.com/shaarli/Shaarli/releases/download/v${version}/shaarli-v${version}-full.tar.gz";
+    sha256 = "sha256-+iFic2WUZ3txiDRNRulznymA3qMqYovePXeP4RMWFUg=";
+  };
+
+  outputs = [ "out" "doc" ];
+
+  patchPhase = ''
+    substituteInPlace index.php \
+      --replace "new ConfigManager();" "new ConfigManager(getenv('SHAARLI_CONFIG'));"
+  '';
+
+#    Point $SHAARLI_CONFIG to your configuration file, see https://github.com/shaarli/Shaarli/wiki/Shaarli-configuration.
+#    For example:
+#      <?php /*
+#      {
+#          "credentials": {
+#              "login": "user",
+#              "hash": "(password hash)",
+#              "salt": "(password salt)"
+#          },
+#          "resource": {
+#              "data_dir": "\/var\/lib\/shaarli",
+#              "config": "\/var\/lib\/shaarli\/config.json.php",
+#              "datastore": "\/var\/lib\/shaarli\/datastore.php",
+#              "ban_file": "\/var\/lib\/shaarli\/ipbans.php",
+#              "updates": "\/var\/lib\/shaarli\/updates.txt",
+#              "log": "\/var\/lib\/shaarli\/log.txt",
+#              "update_check": "\/var\/lib\/shaarli\/lastupdatecheck.txt",
+#              "raintpl_tmp": "\/var\/lib\/shaarli\/tmp",
+#              "thumbnails_cache": "\/var\/lib\/shaarli\/cache",
+#              "page_cache": "\/var\/lib\/shaarli\/pagecache"
+#          },
+#          "updates": {
+#              "check_updates": false
+#          }
+#      }
+#      */ ?>
+
+  installPhase = ''
+    rm -r {cache,pagecache,tmp,data}/
+    mkdir -p $doc/share/doc
+    mv doc/ $doc/share/doc/shaarli
+    mkdir $out/
+    cp -R ./* $out
+  '';
+
+  meta = with lib; {
+    description = "The personal, minimalist, super-fast, database free, bookmarking service";
+    license = licenses.gpl3Plus;
+    homepage = "https://github.com/shaarli/Shaarli";
+    maintainers = with maintainers; [ schneefux ];
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/shiori/default.nix b/nixpkgs/pkgs/servers/web-apps/shiori/default.nix
new file mode 100644
index 000000000000..8a9fc7973f98
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/shiori/default.nix
@@ -0,0 +1,29 @@
+{ lib, buildGoModule, fetchFromGitHub, nixosTests }:
+
+buildGoModule rec {
+  pname = "shiori";
+  version = "1.5.5";
+
+  vendorHash = "sha256-suWdtqf5IZntEVD+NHGD6RsL1tjcGH9vh5skISW+aCc=";
+
+  doCheck = false;
+
+  src = fetchFromGitHub {
+    owner = "go-shiori";
+    repo = pname;
+    rev = "v${version}";
+    sha256 = "sha256-kGPvCYvLLixEH9qih/F3StUyGPqlKukTWLSw41+Mq8E=";
+  };
+
+  passthru.tests = {
+    smoke-test = nixosTests.shiori;
+  };
+
+  meta = with lib; {
+    description = "Simple bookmark manager built with Go";
+    mainProgram = "shiori";
+    homepage = "https://github.com/go-shiori/shiori";
+    license = licenses.mit;
+    maintainers = with maintainers; [ minijackson ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/slskd/default.nix b/nixpkgs/pkgs/servers/web-apps/slskd/default.nix
new file mode 100644
index 000000000000..7a2a388086c1
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/slskd/default.nix
@@ -0,0 +1,60 @@
+{ lib
+, buildNpmPackage
+, fetchFromGitHub
+, dotnetCorePackages
+, buildDotnetModule
+, mono
+, nodejs_18
+}:
+let
+  pname = "slskd";
+  version = "0.19.5";
+
+  src = fetchFromGitHub {
+    owner = "slskd";
+    repo = "slskd";
+    rev = version;
+    sha256 = "sha256-Vm+nA3yKiCMpQ41GTQF6Iuat89QrUtstQdHmX/DyU9g=";
+  };
+
+  meta = with lib; {
+    description = "A modern client-server application for the Soulseek file sharing network";
+    homepage = "https://github.com/slskd/slskd";
+    license = licenses.agpl3Plus;
+    maintainers = with maintainers; [ ppom ];
+    platforms = platforms.linux;
+  };
+
+  wwwroot = buildNpmPackage {
+    inherit meta version;
+
+    pname = "slskd-web";
+    src = "${src}/src/web";
+    npmFlags = [ "--legacy-peer-deps" ];
+    nodejs = nodejs_18;
+    npmDepsHash = "sha256-E1J4fYcY1N+UmN4Ch4Ss6ty+nYlmrv3ngvCJ8YCjPfI=";
+    installPhase = ''
+      cp -r build $out
+    '';
+  };
+
+in buildDotnetModule {
+  inherit pname version src meta;
+
+  runtimeDeps = [ mono ];
+
+  dotnet-sdk = dotnetCorePackages.sdk_7_0;
+  dotnet-runtime = dotnetCorePackages.aspnetcore_7_0;
+
+  projectFile = "slskd.sln";
+
+  testProjectFile = "tests/slskd.Tests.Unit/slskd.Tests.Unit.csproj";
+  doCheck = true;
+
+  nugetDeps = ./deps.nix;
+
+  postInstall = ''
+    rm -r $out/lib/slskd/wwwroot
+    ln -s ${wwwroot} $out/lib/slskd/wwwroot
+  '';
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/slskd/deps.nix b/nixpkgs/pkgs/servers/web-apps/slskd/deps.nix
new file mode 100644
index 000000000000..7de44128b9aa
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/slskd/deps.nix
@@ -0,0 +1,337 @@
+# This file was automatically generated by passthru.fetch-deps.
+# Please dont edit it manually, your changes might get overwritten!
+
+{ fetchNuGet }: [
+  (fetchNuGet { pname = "AutoFixture"; version = "4.18.1"; sha256 = "0whinrvkr2xbhkwd02jbcnws3wz7vlc25hk6w0iw4g92hrmgxqxd"; })
+  (fetchNuGet { pname = "AutoFixture.Xunit2"; version = "4.18.1"; sha256 = "1xs5dbj410h29spdl5c07vrxqkdl3rcyl2fv4jv4g7vq3kanc5p6"; })
+  (fetchNuGet { pname = "Castle.Core"; version = "4.4.0"; sha256 = "0rpcbmyhckvlvp6vbzpj03c1gqz56ixc6f15vgmxmyf1g40c24pf"; })
+  (fetchNuGet { pname = "coverlet.msbuild"; version = "6.0.0"; sha256 = "18qgg6d0ybrr70g69yqamgn5qvpyizlii1123cnj65amd0w2rxjl"; })
+  (fetchNuGet { pname = "Fare"; version = "2.1.1"; sha256 = "1gagj8k2w5m2z6nlywrzhqx1q9n880yriwk0lsq3vcda9lcggmcz"; })
+  (fetchNuGet { pname = "FluentFTP"; version = "48.0.3"; sha256 = "147n6vk3042jm1qspn2jss84qf5v5qh0spv3arpcak2nh61pjrf4"; })
+  (fetchNuGet { pname = "IPAddressRange"; version = "6.0.0"; sha256 = "0fnaxxabamzijj7a418i1z5nnd5ymcjsbplqrj95z8vdw02b99ny"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Authentication.JwtBearer"; version = "7.0.13"; sha256 = "1zzihfm2rwy5z11ndvpi0bx2llghg52msv1mwhgjlrm06q2zff5l"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Connections.Abstractions"; version = "7.0.13"; sha256 = "091cim81z0r0yl33d8qgs5h1xm6r2fwzl4v805arfkjhjr02q3f3"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Http.Connections.Client"; version = "7.0.13"; sha256 = "1wp7dvm9cq3bxz8lxknkjyn9myxlcyr4f0a3296pr48r7jnhafk7"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Http.Connections.Common"; version = "7.0.13"; sha256 = "0n7g7581n9gmpxm2bi0mgxkwj63gva9kmy3njb3zpvvr2vz93fq2"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Mvc.Versioning"; version = "5.1.0"; sha256 = "09v155s17px3d4zm2qz4syj6gdj17sb1a18fzwwvsrs3h357m4c1"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer"; version = "5.1.0"; sha256 = "01bhvs1n7217js1rh3vgl5i2gmxvkgpa3b8i71sv3k8bcz29101l"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.SignalR.Client"; version = "7.0.13"; sha256 = "13mpw2rj0yb68gvjzb0yg5nzl9wi5pg95swmb4lj38vzypbc897p"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.SignalR.Client.Core"; version = "7.0.13"; sha256 = "1lk74hsv3m1sc86cjrbx89a9w7f0a8v38sk6nmig49bk1fkpnb46"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.SignalR.Common"; version = "7.0.13"; sha256 = "0fvajiq24waqxh7pvp3kjnjbj7adhffhm21rmw6l09dvcin8hqwf"; })
+  (fetchNuGet { pname = "Microsoft.AspNetCore.SignalR.Protocols.Json"; version = "7.0.13"; sha256 = "0kzisw542lvcn96n7vk2cwb9n2kb580hxanwahw57x3j8kyz97nz"; })
+  (fetchNuGet { pname = "Microsoft.CodeAnalysis.NetAnalyzers"; version = "7.0.4"; sha256 = "0x0gb6r9lr72jcnv3kkgi01zx1hgpx54niszmrjkdcfivbmmaa81"; })
+  (fetchNuGet { pname = "Microsoft.CodeCoverage"; version = "17.8.0"; sha256 = "173wjadp3gan4x2jfjchngnc4ca4mb95h1sbb28jydfkfw0z1zvj"; })
+  (fetchNuGet { pname = "Microsoft.CSharp"; version = "4.5.0"; sha256 = "01i28nvzccxbqmiz217fxs6hnjwmd5fafs37rd49a6qp53y6623l"; })
+  (fetchNuGet { pname = "Microsoft.CSharp"; version = "4.7.0"; sha256 = "0gd67zlw554j098kabg887b5a6pq9kzavpa3jjy5w53ccjzjfy8j"; })
+  (fetchNuGet { pname = "Microsoft.Data.Sqlite"; version = "7.0.13"; sha256 = "07k00mk8f9pd4gcmx81i3l5kqbih2abc939lixpak7hmqzf3a18r"; })
+  (fetchNuGet { pname = "Microsoft.Data.Sqlite.Core"; version = "7.0.13"; sha256 = "1rnm635jvjyxc7jb9isgarasrhmpvsahv6r6gp4b7li1y2sz3pyv"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore"; version = "7.0.13"; sha256 = "0jmmfcqvxfacgycwdqqrxgimjk83m59w68lpy5vgnqwcbfabg7zj"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore.Abstractions"; version = "7.0.13"; sha256 = "0r36s142lknwx8j9lnxnx70wv3i7f4z6y2d5fi7r2whd3rvidkpq"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore.Analyzers"; version = "7.0.13"; sha256 = "030s0rz3xjdlr77p1s7w0mqs0jrwgsklz63bnm30sxgr6zb25pz3"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore.Relational"; version = "7.0.13"; sha256 = "0kx5056d6qkyxdcpqz46gd344xmizp2w0hknxh1x06bdfsnd292i"; })
+  (fetchNuGet { pname = "Microsoft.EntityFrameworkCore.Sqlite.Core"; version = "7.0.13"; sha256 = "1mrgz6r4nllm3v8lgg1xy53am80kscr8kfh18xzc48w3frxwslr7"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.ApiDescription.Server"; version = "6.0.5"; sha256 = "1pi2bm3cm0a7jzqzmfc2r7bpcdkmk3hhjfvb2c81j7wl7xdw3624"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Caching.Abstractions"; version = "7.0.0"; sha256 = "1hv94kwd4v7969cq3ik2afg5ipn44zbhpsgaga9cd0z47swz4r3a"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Caching.Memory"; version = "7.0.0"; sha256 = "09mq6g61rqjy5mdhsz2224m0rb0z9rkrxhhqym9zwpn272bbc9df"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration"; version = "3.1.0"; sha256 = "1rszgz0rd5kvib5fscz6ss3pkxyjwqy0xpd4f2ypgzf5z5g5d398"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Abstractions"; version = "2.0.0"; sha256 = "1ilz2yrgg9rbjyhn6a5zh9pr51nmh11z7sixb4p7vivgydj9gxwf"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Abstractions"; version = "3.1.0"; sha256 = "1f7h52kamljglx5k08ccryilvk6d6cvr9c26lcb6b2c091znzk0q"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Abstractions"; version = "6.0.0"; sha256 = "0w6wwxv12nbc3sghvr68847wc9skkdgsicrz3fx4chgng1i3xy0j"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Abstractions"; version = "7.0.0"; sha256 = "1as8cygz0pagg17w22nsf6mb49lr2mcl1x8i3ad1wi8lyzygy1a3"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Abstractions"; version = "8.0.0"; sha256 = "1jlpa4ggl1gr5fs7fdcw04li3y3iy05w3klr9lrrlc7v8w76kq71"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Binder"; version = "3.1.0"; sha256 = "13jj7jxihiswmhmql7r5jydbca4x5qj6h7zq10z17gagys6dc7pw"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Configuration.Binder"; version = "8.0.0"; sha256 = "1m0gawiz8f5hc3li9vd5psddlygwgkiw13d7div87kmkf4idza8r"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection"; version = "3.0.0"; sha256 = "0cqbvy49ph16rlba2f35qhi0n7vpcf5kjybvn5fbs7dchfdzw927"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection"; version = "3.1.0"; sha256 = "1xc61dy07bn2q73mx1z3ylrw80xpa682qjby13gklnqq636a3gab"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection"; version = "7.0.0"; sha256 = "121zs4jp8iimgbpzm3wsglhjwkc06irg1pxy8c1zcdlsg34cfq1p"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection"; version = "8.0.0"; sha256 = "0i7qziz0iqmbk8zzln7kx9vd0lbx1x3va0yi3j1bgkjir13h78ps"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "3.0.0"; sha256 = "06s8j8v0w06f12jxw6vvsd0l5zqrmsvc3rr2gqx9z3gcq7mdnr3l"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "3.1.0"; sha256 = "1pvms778xkyv1a3gfwrxnh8ja769cxi416n7pcidn9wvg15ifvbh"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "6.0.0"; sha256 = "1vi67fw7q99gj7jd64gnnfr4d2c0ijpva7g9prps48ja6g91x6a9"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "7.0.0"; sha256 = "181d7mp9307fs17lyy42f8cxnjwysddmpsalky4m0pqxcimnr6g7"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyInjection.Abstractions"; version = "8.0.0"; sha256 = "1zw0bpp5742jzx03wvqc8csnvsbgdqi0ls9jfc5i2vd3cl8b74pg"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyModel"; version = "7.0.0"; sha256 = "04wb6hw3r7mmhg57215r1mb01q17glyaddjw1j5g1drsws914fj4"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.DependencyModel"; version = "8.0.0"; sha256 = "02jnx23hm1vid3yd9pw4gghzn6qkgdl5xfc5r0zrcxdax70rsh5a"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Diagnostics.Abstractions"; version = "8.0.0"; sha256 = "15m4j6w9n8h0mj7hlfzb83hd3wn7aq1s7fxbicm16slsjfwzj82i"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Diagnostics.HealthChecks"; version = "6.0.9"; sha256 = "06mx8zmlmi371ab5pskw8iawy8bbi4vx6rwrcj0andc59zfmg96q"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions"; version = "6.0.9"; sha256 = "1nv2rwq0q7ql63qip5ba45p97yxgva9jg6gnvrnfh2yk2fjwyag2"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Features"; version = "7.0.13"; sha256 = "1sdn9cssq7khq094zb5y8mrp3xapfbmccgm0wgd0chs0h3vxim49"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.FileProviders.Abstractions"; version = "6.0.0"; sha256 = "1fbqmfapxdz77drcv1ndyj2ybvd2rv4c9i9pgiykcpl4fa6dc65q"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.FileProviders.Abstractions"; version = "8.0.0"; sha256 = "1idq65fxwcn882c06yci7nscy9i0rgw6mqjrl7362prvvsd9f15r"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Hosting.Abstractions"; version = "6.0.0"; sha256 = "1mwjx6li4a82nb589763whpnhf5hfy1bpv1dzqqvczb1lhxhzhlj"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Hosting.Abstractions"; version = "8.0.0"; sha256 = "00d5dwmzw76iy8z40ly01hy9gly49a7rpf7k7m99vrid1kxp346h"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Http"; version = "3.1.0"; sha256 = "02ipxf75rqzsbmmy5ka44hh8krmxgky9mdxmh8f7fkbclpg2s6cy"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging"; version = "3.1.0"; sha256 = "1d3yhqj1rav7vswm747j7w8fh8paybji4rz941hhlq4b12mfqfh4"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging"; version = "7.0.0"; sha256 = "1bqd3pqn5dacgnkq0grc17cgb2i0w8z1raw12nwm3p3zhrfcvgxf"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging"; version = "8.0.0"; sha256 = "0nppj34nmq25gnrg0wh1q22y4wdqbih4ax493f226azv8mkp9s1i"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "3.1.0"; sha256 = "1zyalrcksszmn9r5xjnirfh7847axncgzxkk3k5srbvlcch8fw8g"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "6.0.2"; sha256 = "1wv54f3p3r2zj1pr9a6z8zqrh2ihm6v6qcw2pjwis1lcc0qb472m"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "7.0.0"; sha256 = "1gn7d18i1wfy13vrwhmdv1rmsb4vrk26kqdld4cgvh77yigj90xs"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "7.0.1"; sha256 = "0xv3sqc1lbx5j4yy6g2w3kakzvrpwqs2ihax6lqasj5sz5map6fk"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Logging.Abstractions"; version = "8.0.0"; sha256 = "1klcqhg3hk55hb6vmjiq2wgqidsl81aldw0li2z98lrwx26msrr6"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.ObjectPool"; version = "7.0.0"; sha256 = "15lz0qk2gr2q52i05ip51dzm9p4hzqlrammkc0hv2ng6g0z72697"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options"; version = "3.1.0"; sha256 = "0akccwhpn93a4qrssyb3rszdsp3j4p9hlxbsb7yhqb78xydaqhyh"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options"; version = "6.0.0"; sha256 = "008pnk2p50i594ahz308v81a41mbjz9mwcarqhmrjpl2d20c868g"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options"; version = "7.0.0"; sha256 = "0b90zkrsk5dw3wr749rbynhpxlg4bgqdnd7d5vdlw2g9c7zlhgx6"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options"; version = "7.0.1"; sha256 = "0ghz4y4gxnf2vw8yvhz9nkw21p6q2qqwh19phkk1xwxywyilr3mq"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Options"; version = "8.0.0"; sha256 = "0p50qn6zhinzyhq9sy5svnmqqwhw2jajs2pbjh9sah504wjvhscz"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Primitives"; version = "2.0.0"; sha256 = "1xppr5jbny04slyjgngxjdm0maxdh47vq481ps944d7jrfs0p3mb"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Primitives"; version = "3.1.0"; sha256 = "1w1y22njywwysi8qjnj4m83qhbq0jr4mmjib0hfawz6cwamh7xrb"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Primitives"; version = "6.0.0"; sha256 = "1kjiw6s4yfz9gm7mx3wkhp06ghnbs95icj9hi505shz9rjrg42q2"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Primitives"; version = "7.0.0"; sha256 = "1b4km9fszid9vp2zb3gya5ni9fn8bq62bzaas2ck2r7gs0sdys80"; })
+  (fetchNuGet { pname = "Microsoft.Extensions.Primitives"; version = "8.0.0"; sha256 = "0aldaz5aapngchgdr7dax9jw5wy7k7hmjgjpfgfv1wfif27jlkqm"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Abstractions"; version = "7.0.3"; sha256 = "0njmg2lygnirnfjv9gck2f5lq4ly5rgws9cpf8qj3kwcwxfp0b9s"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.JsonWebTokens"; version = "7.0.3"; sha256 = "1ayh85xqdq8rqjk2iqcn7iaczcl7d8qg6bxk0b4rgx59fmsmbqj7"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Logging"; version = "6.15.1"; sha256 = "1jnswvv5d6gbnssmql08d72pb0a42xscp4k5k1svsk8k5pj3nf8p"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Logging"; version = "7.0.3"; sha256 = "13cjqmf59k895q6gkd5ycl89mnpalckda7rhsdl11jdyr32hsfnv"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Protocols"; version = "6.15.1"; sha256 = "1075g2g30g7qmznc9mf97nm4k4xbz4s37bi59qxwbx0y2pnl1f2r"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Protocols.OpenIdConnect"; version = "6.15.1"; sha256 = "19sbh8hxbbp24294k8vc6z92906wq366m49k5484mngwrw5jpsyf"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Tokens"; version = "6.15.1"; sha256 = "1ljg7nrxjkfcwh081831s30agpfx8f3flqvwg5piy6vfc9hqmxa8"; })
+  (fetchNuGet { pname = "Microsoft.IdentityModel.Tokens"; version = "7.0.3"; sha256 = "1pmhd0imh9wlhvbvvwjrpjsqvzagi2ly22nddwr4r0pi234khyz1"; })
+  (fetchNuGet { pname = "Microsoft.NET.Test.Sdk"; version = "17.8.0"; sha256 = "1syvl3g0hbrcgfi9rq6pld8s8hqqww4dflf1lxn59ccddyyx0gmv"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Platforms"; version = "1.0.1"; sha256 = "01al6cfxp68dscl15z7rxfw9zvhm64dncsw09a1vmdkacsa2v6lr"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Platforms"; version = "1.1.0"; sha256 = "08vh1r12g6ykjygq5d3vq09zylgb84l63k49jc4v8faw9g93iqqm"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Targets"; version = "1.0.1"; sha256 = "0ppdkwy6s9p7x9jix3v4402wb171cdiibq7js7i13nxpdky7074p"; })
+  (fetchNuGet { pname = "Microsoft.NETCore.Targets"; version = "1.1.0"; sha256 = "193xwf33fbm0ni3idxzbr5fdq3i2dlfgihsac9jj7whj0gd902nh"; })
+  (fetchNuGet { pname = "Microsoft.OpenApi"; version = "1.2.3"; sha256 = "07b19k89whj69j87afkz86gp9b3iybw8jqwvlgcn43m7fb2y99rr"; })
+  (fetchNuGet { pname = "Microsoft.TestPlatform.ObjectModel"; version = "17.8.0"; sha256 = "0b0i7lmkrcfvim8i3l93gwqvkhhhfzd53fqfnygdqvkg6np0cg7m"; })
+  (fetchNuGet { pname = "Microsoft.TestPlatform.TestHost"; version = "17.8.0"; sha256 = "0f5jah93kjkvxwmhwb78lw11m9pkkq9fvf135hpymmmpxqbdh97q"; })
+  (fetchNuGet { pname = "Microsoft.Win32.Primitives"; version = "4.0.1"; sha256 = "1n8ap0cmljbqskxpf8fjzn7kh1vvlndsa75k01qig26mbw97k2q7"; })
+  (fetchNuGet { pname = "Microsoft.Win32.Primitives"; version = "4.3.0"; sha256 = "0j0c1wj4ndj21zsgivsc24whiya605603kxrbiw6wkfdync464wq"; })
+  (fetchNuGet { pname = "Mono.Posix.NETStandard"; version = "1.0.0"; sha256 = "0xlja36hwpjm837haq15mjh2prcf68lyrmn72nvgpz8qnf9vappw"; })
+  (fetchNuGet { pname = "Moq"; version = "4.16.1"; sha256 = "1m2gwbx0gsy84rl9c3hgdaw9gz8d08ffg19nwg0idsdqmmiq887l"; })
+  (fetchNuGet { pname = "NETStandard.Library"; version = "1.6.0"; sha256 = "0nmmv4yw7gw04ik8ialj3ak0j6pxa9spih67hnn1h2c38ba8h58k"; })
+  (fetchNuGet { pname = "NETStandard.Library"; version = "1.6.1"; sha256 = "1z70wvsx2d847a2cjfii7b83pjfs34q05gb037fdjikv5kbagml8"; })
+  (fetchNuGet { pname = "Newtonsoft.Json"; version = "13.0.1"; sha256 = "0fijg0w6iwap8gvzyjnndds0q4b8anwxxvik7y8vgq97dram4srb"; })
+  (fetchNuGet { pname = "NuGet.Frameworks"; version = "6.5.0"; sha256 = "0s37d1p4md0k6d4cy6sq36f2dgkd9qfbzapxhkvi8awwh0vrynhj"; })
+  (fetchNuGet { pname = "OneOf"; version = "3.0.263"; sha256 = "08jiy5ff6nx3bbmia7iqcfrva0bynr87m0m4nxkzm5ri21w49ri1"; })
+  (fetchNuGet { pname = "prometheus-net"; version = "8.2.0"; sha256 = "19m9lkpc4h9a0jmn66p61x8960gk9fidcwic70nrvjhmd5m201fj"; })
+  (fetchNuGet { pname = "prometheus-net.AspNetCore"; version = "8.2.0"; sha256 = "1lilk7xw19wgl2i7cjbf09ssd4jicla45wj29hfy6d1bzcnd6yn8"; })
+  (fetchNuGet { pname = "prometheus-net.AspNetCore.HealthChecks"; version = "8.2.0"; sha256 = "1kzvlab31ypgp62663nnr6g964w19iabnyilqlkm6acl5f5vvfvv"; })
+  (fetchNuGet { pname = "prometheus-net.DotNetRuntime"; version = "4.4.0"; sha256 = "1hrzf2djkjiswyf4xg3pl6rb0a8i0mh294hrfbna782hfxya7c29"; })
+  (fetchNuGet { pname = "prometheus-net.SystemMetrics"; version = "3.0.0"; sha256 = "0gl1msasy19vy836dzwkp8046f141nlrx0fhzg70vzfzjnrh3jm5"; })
+  (fetchNuGet { pname = "runtime.any.System.Collections"; version = "4.3.0"; sha256 = "0bv5qgm6vr47ynxqbnkc7i797fdi8gbjjxii173syrx14nmrkwg0"; })
+  (fetchNuGet { pname = "runtime.any.System.Diagnostics.Tools"; version = "4.3.0"; sha256 = "1wl76vk12zhdh66vmagni66h5xbhgqq7zkdpgw21jhxhvlbcl8pk"; })
+  (fetchNuGet { pname = "runtime.any.System.Diagnostics.Tracing"; version = "4.3.0"; sha256 = "00j6nv2xgmd3bi347k00m7wr542wjlig53rmj28pmw7ddcn97jbn"; })
+  (fetchNuGet { pname = "runtime.any.System.Globalization"; version = "4.3.0"; sha256 = "1daqf33hssad94lamzg01y49xwndy2q97i2lrb7mgn28656qia1x"; })
+  (fetchNuGet { pname = "runtime.any.System.Globalization.Calendars"; version = "4.3.0"; sha256 = "1ghhhk5psqxcg6w88sxkqrc35bxcz27zbqm2y5p5298pv3v7g201"; })
+  (fetchNuGet { pname = "runtime.any.System.IO"; version = "4.3.0"; sha256 = "0l8xz8zn46w4d10bcn3l4yyn4vhb3lrj2zw8llvz7jk14k4zps5x"; })
+  (fetchNuGet { pname = "runtime.any.System.Reflection"; version = "4.3.0"; sha256 = "02c9h3y35pylc0zfq3wcsvc5nqci95nrkq0mszifc0sjx7xrzkly"; })
+  (fetchNuGet { pname = "runtime.any.System.Reflection.Extensions"; version = "4.3.0"; sha256 = "0zyri97dfc5vyaz9ba65hjj1zbcrzaffhsdlpxc9bh09wy22fq33"; })
+  (fetchNuGet { pname = "runtime.any.System.Reflection.Primitives"; version = "4.3.0"; sha256 = "0x1mm8c6iy8rlxm8w9vqw7gb7s1ljadrn049fmf70cyh42vdfhrf"; })
+  (fetchNuGet { pname = "runtime.any.System.Resources.ResourceManager"; version = "4.3.0"; sha256 = "03kickal0iiby82wa5flar18kyv82s9s6d4xhk5h4bi5kfcyfjzl"; })
+  (fetchNuGet { pname = "runtime.any.System.Runtime"; version = "4.3.0"; sha256 = "1cqh1sv3h5j7ixyb7axxbdkqx6cxy00p4np4j91kpm492rf4s25b"; })
+  (fetchNuGet { pname = "runtime.any.System.Runtime.Handles"; version = "4.3.0"; sha256 = "0bh5bi25nk9w9xi8z23ws45q5yia6k7dg3i4axhfqlnj145l011x"; })
+  (fetchNuGet { pname = "runtime.any.System.Runtime.InteropServices"; version = "4.3.0"; sha256 = "0c3g3g3jmhlhw4klrc86ka9fjbl7i59ds1fadsb2l8nqf8z3kb19"; })
+  (fetchNuGet { pname = "runtime.any.System.Text.Encoding"; version = "4.3.0"; sha256 = "0aqqi1v4wx51h51mk956y783wzags13wa7mgqyclacmsmpv02ps3"; })
+  (fetchNuGet { pname = "runtime.any.System.Text.Encoding.Extensions"; version = "4.3.0"; sha256 = "0lqhgqi0i8194ryqq6v2gqx0fb86db2gqknbm0aq31wb378j7ip8"; })
+  (fetchNuGet { pname = "runtime.any.System.Threading.Tasks"; version = "4.3.0"; sha256 = "03mnvkhskbzxddz4hm113zsch1jyzh2cs450dk3rgfjp8crlw1va"; })
+  (fetchNuGet { pname = "runtime.any.System.Threading.Timer"; version = "4.3.0"; sha256 = "0aw4phrhwqz9m61r79vyfl5la64bjxj8l34qnrcwb28v49fg2086"; })
+  (fetchNuGet { pname = "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "16rnxzpk5dpbbl1x354yrlsbvwylrq456xzpsha1n9y3glnhyx9d"; })
+  (fetchNuGet { pname = "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0hkg03sgm2wyq8nqk6dbm9jh5vcq57ry42lkqdmfklrw89lsmr59"; })
+  (fetchNuGet { pname = "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0c2p354hjx58xhhz7wv6div8xpi90sc6ibdm40qin21bvi7ymcaa"; })
+  (fetchNuGet { pname = "runtime.native.System"; version = "4.0.0"; sha256 = "1ppk69xk59ggacj9n7g6fyxvzmk1g5p4fkijm0d7xqfkig98qrkf"; })
+  (fetchNuGet { pname = "runtime.native.System"; version = "4.3.0"; sha256 = "15hgf6zaq9b8br2wi1i3x0zvmk410nlmsmva9p0bbg73v6hml5k4"; })
+  (fetchNuGet { pname = "runtime.native.System.IO.Compression"; version = "4.1.0"; sha256 = "0d720z4lzyfcabmmnvh0bnj76ll7djhji2hmfh3h44sdkjnlkknk"; })
+  (fetchNuGet { pname = "runtime.native.System.IO.Compression"; version = "4.3.0"; sha256 = "1vvivbqsk6y4hzcid27pqpm5bsi6sc50hvqwbcx8aap5ifrxfs8d"; })
+  (fetchNuGet { pname = "runtime.native.System.Net.Http"; version = "4.0.1"; sha256 = "1hgv2bmbaskx77v8glh7waxws973jn4ah35zysnkxmf0196sfxg6"; })
+  (fetchNuGet { pname = "runtime.native.System.Net.Http"; version = "4.3.0"; sha256 = "1n6rgz5132lcibbch1qlf0g9jk60r0kqv087hxc0lisy50zpm7kk"; })
+  (fetchNuGet { pname = "runtime.native.System.Security.Cryptography"; version = "4.0.0"; sha256 = "0k57aa2c3b10wl3hfqbgrl7xq7g8hh3a3ir44b31dn5p61iiw3z9"; })
+  (fetchNuGet { pname = "runtime.native.System.Security.Cryptography.Apple"; version = "4.3.0"; sha256 = "1b61p6gw1m02cc1ry996fl49liiwky6181dzr873g9ds92zl326q"; })
+  (fetchNuGet { pname = "runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "18pzfdlwsg2nb1jjjjzyb5qlgy6xjxzmhnfaijq5s2jw3cm3ab97"; })
+  (fetchNuGet { pname = "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0qyynf9nz5i7pc26cwhgi8j62ps27sqmf78ijcfgzab50z9g8ay3"; })
+  (fetchNuGet { pname = "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "1klrs545awhayryma6l7g2pvnp9xy4z0r1i40r80zb45q3i9nbyf"; })
+  (fetchNuGet { pname = "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple"; version = "4.3.0"; sha256 = "10yc8jdrwgcl44b4g93f1ds76b176bajd3zqi2faf5rvh1vy9smi"; })
+  (fetchNuGet { pname = "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0zcxjv5pckplvkg0r6mw3asggm7aqzbdjimhvsasb0cgm59x09l3"; })
+  (fetchNuGet { pname = "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0vhynn79ih7hw7cwjazn87rm9z9fj0rvxgzlab36jybgcpcgphsn"; })
+  (fetchNuGet { pname = "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "160p68l2c7cqmyqjwxydcvgw7lvl1cr0znkw8fp24d1by9mqc8p3"; })
+  (fetchNuGet { pname = "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "15zrc8fgd8zx28hdghcj5f5i34wf3l6bq5177075m2bc2j34jrqy"; })
+  (fetchNuGet { pname = "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "1p4dgxax6p7rlgj4q73k73rslcnz4wdcv8q2flg1s8ygwcm58ld5"; })
+  (fetchNuGet { pname = "runtime.unix.Microsoft.Win32.Primitives"; version = "4.3.0"; sha256 = "0y61k9zbxhdi0glg154v30kkq7f8646nif8lnnxbvkjpakggd5id"; })
+  (fetchNuGet { pname = "runtime.unix.System.Console"; version = "4.3.0"; sha256 = "1pfpkvc6x2if8zbdzg9rnc5fx51yllprl8zkm5npni2k50lisy80"; })
+  (fetchNuGet { pname = "runtime.unix.System.Diagnostics.Debug"; version = "4.3.0"; sha256 = "1lps7fbnw34bnh3lm31gs5c0g0dh7548wfmb8zz62v0zqz71msj5"; })
+  (fetchNuGet { pname = "runtime.unix.System.IO.FileSystem"; version = "4.3.0"; sha256 = "14nbkhvs7sji5r1saj2x8daz82rnf9kx28d3v2qss34qbr32dzix"; })
+  (fetchNuGet { pname = "runtime.unix.System.Net.Primitives"; version = "4.3.0"; sha256 = "0bdnglg59pzx9394sy4ic66kmxhqp8q8bvmykdxcbs5mm0ipwwm4"; })
+  (fetchNuGet { pname = "runtime.unix.System.Net.Sockets"; version = "4.3.0"; sha256 = "03npdxzy8gfv035bv1b9rz7c7hv0rxl5904wjz51if491mw0xy12"; })
+  (fetchNuGet { pname = "runtime.unix.System.Private.Uri"; version = "4.3.0"; sha256 = "1jx02q6kiwlvfksq1q9qr17fj78y5v6mwsszav4qcz9z25d5g6vk"; })
+  (fetchNuGet { pname = "runtime.unix.System.Runtime.Extensions"; version = "4.3.0"; sha256 = "0pnxxmm8whx38dp6yvwgmh22smknxmqs5n513fc7m4wxvs1bvi4p"; })
+  (fetchNuGet { pname = "Serilog"; version = "3.1.1"; sha256 = "0ck51ndmaqflsri7yyw5792z42wsp91038rx2i6vg7z4r35vfvig"; })
+  (fetchNuGet { pname = "Serilog.AspNetCore"; version = "8.0.0"; sha256 = "0g1scn1a5paiydxk1nnrwzzqny2vabc3hniy6jwjqycag6ch2pni"; })
+  (fetchNuGet { pname = "Serilog.Extensions.Hosting"; version = "8.0.0"; sha256 = "10cgp4nsrzkld5yxnvkfkwd0wkc1m8m7p5z42w4sqd8f188n8i9q"; })
+  (fetchNuGet { pname = "Serilog.Extensions.Logging"; version = "8.0.0"; sha256 = "087ab94sfhkj6h6x3cwwf66g456704faxnfyc4pi6shxk45b318s"; })
+  (fetchNuGet { pname = "Serilog.Formatting.Compact"; version = "2.0.0"; sha256 = "0y7vg2qji02riq7r0kgybarhkngw6gh3xw89w7c2hcmjawd96x3k"; })
+  (fetchNuGet { pname = "Serilog.Settings.Configuration"; version = "8.0.0"; sha256 = "0245gvndwbj4nbp8q09vp7w4i9iddxr0vzda2c3ja5afz1zgs395"; })
+  (fetchNuGet { pname = "Serilog.Sinks.Async"; version = "1.5.0"; sha256 = "0bcb3n6lmg5wfj806mziybfmbb8gyiszrivs3swf0msy8w505gyg"; })
+  (fetchNuGet { pname = "Serilog.Sinks.Console"; version = "5.0.1"; sha256 = "0cnjjpnnhlx3k4385dbnddkz3n6khdshjix0hlv4gjmrrmjaixva"; })
+  (fetchNuGet { pname = "Serilog.Sinks.Debug"; version = "2.0.0"; sha256 = "1i7j870l47gan3gpnnlzkccn5lbm7518cnkp25a3g5gp9l0dbwpw"; })
+  (fetchNuGet { pname = "Serilog.Sinks.File"; version = "5.0.0"; sha256 = "097rngmgcrdfy7jy8j7dq3xaq2qky8ijwg0ws6bfv5lx0f3vvb0q"; })
+  (fetchNuGet { pname = "Serilog.Sinks.Grafana.Loki"; version = "7.1.1"; sha256 = "1c7csknq5v09j2x3ybrssxk59aca9x678j53wp73ryjh0niqxznl"; })
+  (fetchNuGet { pname = "Serilog.Sinks.Http"; version = "8.0.0"; sha256 = "1sx30n2cn5ixfvxs8llgk19r0vvv27246341bjy2h4994sl8zgld"; })
+  (fetchNuGet { pname = "Soulseek"; version = "6.2.0"; sha256 = "1nz4fcqpf4mqbc8ig1311vkcn11wcx3nayk56cn7syqczpdqzqxv"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.bundle_e_sqlite3"; version = "2.1.4"; sha256 = "0shdspl9cm71wwqg9103s44r0l01r3sgnpxr523y4a0wlgac50g0"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.core"; version = "2.1.4"; sha256 = "09akxz92qipr1cj8mk2hw99i0b81wwbwx26gpk21471zh543f8ld"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.lib.e_sqlite3"; version = "2.1.4"; sha256 = "11l85ksv1ck46j8z08fyf0c3l572zmp9ynb7p5chm5iyrh8xwkkn"; })
+  (fetchNuGet { pname = "SQLitePCLRaw.provider.e_sqlite3"; version = "2.1.4"; sha256 = "0b8f51nrjkq0pmfzjaqk5rp7r0cp2lbdm2whynj3xsjklppzmn35"; })
+  (fetchNuGet { pname = "StyleCop.Analyzers"; version = "1.2.0-beta.435"; sha256 = "0dirz0av24ds2k7hgpss15y4wlhwlzz22qdjvkq0n3g3sxcckrsy"; })
+  (fetchNuGet { pname = "StyleCop.Analyzers.Unstable"; version = "1.2.0.435"; sha256 = "1jv4ha4y2c9922n21yf2dvfkmi8qfa8z28gk5zsqdyck08izp9mh"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore"; version = "6.5.0"; sha256 = "0k61chpz5j59s1yax28vx0mppx20ff8vg8grwja112hfrzj1f45n"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore.Swagger"; version = "6.5.0"; sha256 = "1s6axf6fin8sss3bvzp0s039rxrx71vx4rl559miw12bz3lld8kc"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore.SwaggerGen"; version = "6.5.0"; sha256 = "0hq93gy5vyrigpdk9lhqwxglxwkbxa8ydllwcqs4bwfcsspzrs83"; })
+  (fetchNuGet { pname = "Swashbuckle.AspNetCore.SwaggerUI"; version = "6.5.0"; sha256 = "17hx7kc187higm0gk67dndng3n7932sn3fwyj48l45cvyr3025h7"; })
+  (fetchNuGet { pname = "System.AppContext"; version = "4.1.0"; sha256 = "0fv3cma1jp4vgj7a8hqc9n7hr1f1kjp541s6z0q1r6nazb4iz9mz"; })
+  (fetchNuGet { pname = "System.AppContext"; version = "4.3.0"; sha256 = "1649qvy3dar900z3g817h17nl8jp4ka5vcfmsr05kh0fshn7j3ya"; })
+  (fetchNuGet { pname = "System.Buffers"; version = "4.0.0"; sha256 = "13s659bcmg9nwb6z78971z1lr6bmh2wghxi1ayqyzl4jijd351gr"; })
+  (fetchNuGet { pname = "System.Buffers"; version = "4.3.0"; sha256 = "0fgns20ispwrfqll4q1zc1waqcmylb3zc50ys9x8zlwxh9pmd9jy"; })
+  (fetchNuGet { pname = "System.Collections"; version = "4.0.11"; sha256 = "1ga40f5lrwldiyw6vy67d0sg7jd7ww6kgwbksm19wrvq9hr0bsm6"; })
+  (fetchNuGet { pname = "System.Collections"; version = "4.3.0"; sha256 = "19r4y64dqyrq6k4706dnyhhw7fs24kpp3awak7whzss39dakpxk9"; })
+  (fetchNuGet { pname = "System.Collections.Concurrent"; version = "4.0.12"; sha256 = "07y08kvrzpak873pmyxs129g1ch8l27zmg51pcyj2jvq03n0r0fc"; })
+  (fetchNuGet { pname = "System.Collections.Concurrent"; version = "4.3.0"; sha256 = "0wi10md9aq33jrkh2c24wr2n9hrpyamsdhsxdcnf43b7y86kkii8"; })
+  (fetchNuGet { pname = "System.Collections.NonGeneric"; version = "4.3.0"; sha256 = "07q3k0hf3mrcjzwj8fwk6gv3n51cb513w4mgkfxzm3i37sc9kz7k"; })
+  (fetchNuGet { pname = "System.Collections.Specialized"; version = "4.3.0"; sha256 = "1sdwkma4f6j85m3dpb53v9vcgd0zyc9jb33f8g63byvijcj39n20"; })
+  (fetchNuGet { pname = "System.ComponentModel"; version = "4.3.0"; sha256 = "0986b10ww3nshy30x9sjyzm0jx339dkjxjj3401r3q0f6fx2wkcb"; })
+  (fetchNuGet { pname = "System.ComponentModel.Annotations"; version = "4.3.0"; sha256 = "1ab25njbjgqbnvkazv41ndc0fc7gx0dnnhzb57d2wbd7ljxm21fd"; })
+  (fetchNuGet { pname = "System.ComponentModel.Primitives"; version = "4.3.0"; sha256 = "1svfmcmgs0w0z9xdw2f2ps05rdxmkxxhf0l17xk9l1l8xfahkqr0"; })
+  (fetchNuGet { pname = "System.ComponentModel.TypeConverter"; version = "4.3.0"; sha256 = "17ng0p7v3nbrg3kycz10aqrrlw4lz9hzhws09pfh8gkwicyy481x"; })
+  (fetchNuGet { pname = "System.Configuration.ConfigurationManager"; version = "8.0.0"; sha256 = "08dadpd8lx6x7craw3h3444p7ncz4wk0a3j1681lyhhd56ln66f6"; })
+  (fetchNuGet { pname = "System.Console"; version = "4.0.0"; sha256 = "0ynxqbc3z1nwbrc11hkkpw9skw116z4y9wjzn7id49p9yi7mzmlf"; })
+  (fetchNuGet { pname = "System.Console"; version = "4.3.0"; sha256 = "1flr7a9x920mr5cjsqmsy9wgnv3lvd0h1g521pdr1lkb2qycy7ay"; })
+  (fetchNuGet { pname = "System.Diagnostics.Debug"; version = "4.0.11"; sha256 = "0gmjghrqmlgzxivd2xl50ncbglb7ljzb66rlx8ws6dv8jm0d5siz"; })
+  (fetchNuGet { pname = "System.Diagnostics.Debug"; version = "4.3.0"; sha256 = "00yjlf19wjydyr6cfviaph3vsjzg3d5nvnya26i2fvfg53sknh3y"; })
+  (fetchNuGet { pname = "System.Diagnostics.DiagnosticSource"; version = "4.0.0"; sha256 = "1n6c3fbz7v8d3pn77h4v5wvsfrfg7v1c57lg3nff3cjyh597v23m"; })
+  (fetchNuGet { pname = "System.Diagnostics.DiagnosticSource"; version = "4.3.0"; sha256 = "0z6m3pbiy0qw6rn3n209rrzf9x1k4002zh90vwcrsym09ipm2liq"; })
+  (fetchNuGet { pname = "System.Diagnostics.DiagnosticSource"; version = "8.0.0"; sha256 = "0nzra1i0mljvmnj1qqqg37xs7bl71fnpl68nwmdajchh65l878zr"; })
+  (fetchNuGet { pname = "System.Diagnostics.EventLog"; version = "8.0.0"; sha256 = "1xnvcidh2qf6k7w8ij1rvj0viqkq84cq47biw0c98xhxg5rk3pxf"; })
+  (fetchNuGet { pname = "System.Diagnostics.PerformanceCounter"; version = "8.0.0"; sha256 = "16dviw76i17kzprh6famsnng97znzzd0d6zj4l28grfwibxcpd09"; })
+  (fetchNuGet { pname = "System.Diagnostics.Tools"; version = "4.0.1"; sha256 = "19cknvg07yhakcvpxg3cxa0bwadplin6kyxd8mpjjpwnp56nl85x"; })
+  (fetchNuGet { pname = "System.Diagnostics.Tools"; version = "4.3.0"; sha256 = "0in3pic3s2ddyibi8cvgl102zmvp9r9mchh82ns9f0ms4basylw1"; })
+  (fetchNuGet { pname = "System.Diagnostics.TraceSource"; version = "4.3.0"; sha256 = "1kyw4d7dpjczhw6634nrmg7yyyzq72k75x38y0l0nwhigdlp1766"; })
+  (fetchNuGet { pname = "System.Diagnostics.Tracing"; version = "4.1.0"; sha256 = "1d2r76v1x610x61ahfpigda89gd13qydz6vbwzhpqlyvq8jj6394"; })
+  (fetchNuGet { pname = "System.Diagnostics.Tracing"; version = "4.3.0"; sha256 = "1m3bx6c2s958qligl67q7grkwfz3w53hpy7nc97mh6f7j5k168c4"; })
+  (fetchNuGet { pname = "System.Dynamic.Runtime"; version = "4.3.0"; sha256 = "1d951hrvrpndk7insiag80qxjbf2y0y39y8h5hnq9612ws661glk"; })
+  (fetchNuGet { pname = "System.Globalization"; version = "4.0.11"; sha256 = "070c5jbas2v7smm660zaf1gh0489xanjqymkvafcs4f8cdrs1d5d"; })
+  (fetchNuGet { pname = "System.Globalization"; version = "4.3.0"; sha256 = "1cp68vv683n6ic2zqh2s1fn4c2sd87g5hpp6l4d4nj4536jz98ki"; })
+  (fetchNuGet { pname = "System.Globalization.Calendars"; version = "4.0.1"; sha256 = "0bv0alrm2ck2zk3rz25lfyk9h42f3ywq77mx1syl6vvyncnpg4qh"; })
+  (fetchNuGet { pname = "System.Globalization.Calendars"; version = "4.3.0"; sha256 = "1xwl230bkakzzkrggy1l1lxmm3xlhk4bq2pkv790j5lm8g887lxq"; })
+  (fetchNuGet { pname = "System.Globalization.Extensions"; version = "4.0.1"; sha256 = "0hjhdb5ri8z9l93bw04s7ynwrjrhx2n0p34sf33a9hl9phz69fyc"; })
+  (fetchNuGet { pname = "System.Globalization.Extensions"; version = "4.3.0"; sha256 = "02a5zfxavhv3jd437bsncbhd2fp1zv4gxzakp1an9l6kdq1mcqls"; })
+  (fetchNuGet { pname = "System.IdentityModel.Tokens.Jwt"; version = "7.0.3"; sha256 = "1fls88ffq34j1gr6zay1crm27v3sjs5fa4mvj9akqjq05bxanlhk"; })
+  (fetchNuGet { pname = "System.IO"; version = "4.1.0"; sha256 = "1g0yb8p11vfd0kbkyzlfsbsp5z44lwsvyc0h3dpw6vqnbi035ajp"; })
+  (fetchNuGet { pname = "System.IO"; version = "4.3.0"; sha256 = "05l9qdrzhm4s5dixmx68kxwif4l99ll5gqmh7rqgw554fx0agv5f"; })
+  (fetchNuGet { pname = "System.IO.Compression"; version = "4.1.0"; sha256 = "0iym7s3jkl8n0vzm3jd6xqg9zjjjqni05x45dwxyjr2dy88hlgji"; })
+  (fetchNuGet { pname = "System.IO.Compression"; version = "4.3.0"; sha256 = "084zc82yi6yllgda0zkgl2ys48sypiswbiwrv7irb3r0ai1fp4vz"; })
+  (fetchNuGet { pname = "System.IO.Compression.ZipFile"; version = "4.0.1"; sha256 = "0h72znbagmgvswzr46mihn7xm7chfk2fhrp5krzkjf29pz0i6z82"; })
+  (fetchNuGet { pname = "System.IO.Compression.ZipFile"; version = "4.3.0"; sha256 = "1yxy5pq4dnsm9hlkg9ysh5f6bf3fahqqb6p8668ndy5c0lk7w2ar"; })
+  (fetchNuGet { pname = "System.IO.FileSystem"; version = "4.0.1"; sha256 = "0kgfpw6w4djqra3w5crrg8xivbanh1w9dh3qapb28q060wb9flp1"; })
+  (fetchNuGet { pname = "System.IO.FileSystem"; version = "4.3.0"; sha256 = "0z2dfrbra9i6y16mm9v1v6k47f0fm617vlb7s5iybjjsz6g1ilmw"; })
+  (fetchNuGet { pname = "System.IO.FileSystem.Primitives"; version = "4.0.1"; sha256 = "1s0mniajj3lvbyf7vfb5shp4ink5yibsx945k6lvxa96r8la1612"; })
+  (fetchNuGet { pname = "System.IO.FileSystem.Primitives"; version = "4.3.0"; sha256 = "0j6ndgglcf4brg2lz4wzsh1av1gh8xrzdsn9f0yznskhqn1xzj9c"; })
+  (fetchNuGet { pname = "System.IO.Pipelines"; version = "7.0.0"; sha256 = "1ila2vgi1w435j7g2y7ykp2pdbh9c5a02vm85vql89az93b7qvav"; })
+  (fetchNuGet { pname = "System.Linq"; version = "4.1.0"; sha256 = "1ppg83svb39hj4hpp5k7kcryzrf3sfnm08vxd5sm2drrijsla2k5"; })
+  (fetchNuGet { pname = "System.Linq"; version = "4.3.0"; sha256 = "1w0gmba695rbr80l1k2h4mrwzbzsyfl2z4klmpbsvsg5pm4a56s7"; })
+  (fetchNuGet { pname = "System.Linq.Expressions"; version = "4.1.0"; sha256 = "1gpdxl6ip06cnab7n3zlcg6mqp7kknf73s8wjinzi4p0apw82fpg"; })
+  (fetchNuGet { pname = "System.Linq.Expressions"; version = "4.3.0"; sha256 = "0ky2nrcvh70rqq88m9a5yqabsl4fyd17bpr63iy2mbivjs2nyypv"; })
+  (fetchNuGet { pname = "System.Memory"; version = "4.5.3"; sha256 = "0naqahm3wljxb5a911d37mwjqjdxv9l0b49p5dmfyijvni2ppy8a"; })
+  (fetchNuGet { pname = "System.Memory"; version = "4.5.5"; sha256 = "08jsfwimcarfzrhlyvjjid61j02irx6xsklf32rv57x2aaikvx0h"; })
+  (fetchNuGet { pname = "System.Net.Http"; version = "4.1.0"; sha256 = "1i5rqij1icg05j8rrkw4gd4pgia1978mqhjzhsjg69lvwcdfg8yb"; })
+  (fetchNuGet { pname = "System.Net.Http"; version = "4.3.0"; sha256 = "1i4gc757xqrzflbk7kc5ksn20kwwfjhw9w7pgdkn19y3cgnl302j"; })
+  (fetchNuGet { pname = "System.Net.NameResolution"; version = "4.3.0"; sha256 = "15r75pwc0rm3vvwsn8rvm2krf929mjfwliv0mpicjnii24470rkq"; })
+  (fetchNuGet { pname = "System.Net.Primitives"; version = "4.0.11"; sha256 = "10xzzaynkzkakp7jai1ik3r805zrqjxiz7vcagchyxs2v26a516r"; })
+  (fetchNuGet { pname = "System.Net.Primitives"; version = "4.3.0"; sha256 = "0c87k50rmdgmxx7df2khd9qj7q35j9rzdmm2572cc55dygmdk3ii"; })
+  (fetchNuGet { pname = "System.Net.Sockets"; version = "4.1.0"; sha256 = "1385fvh8h29da5hh58jm1v78fzi9fi5vj93vhlm2kvqpfahvpqls"; })
+  (fetchNuGet { pname = "System.Net.Sockets"; version = "4.3.0"; sha256 = "1ssa65k6chcgi6mfmzrznvqaxk8jp0gvl77xhf1hbzakjnpxspla"; })
+  (fetchNuGet { pname = "System.ObjectModel"; version = "4.0.12"; sha256 = "1sybkfi60a4588xn34nd9a58png36i0xr4y4v4kqpg8wlvy5krrj"; })
+  (fetchNuGet { pname = "System.ObjectModel"; version = "4.3.0"; sha256 = "191p63zy5rpqx7dnrb3h7prvgixmk168fhvvkkvhlazncf8r3nc2"; })
+  (fetchNuGet { pname = "System.Private.Uri"; version = "4.3.0"; sha256 = "04r1lkdnsznin0fj4ya1zikxiqr0h6r6a1ww2dsm60gqhdrf0mvx"; })
+  (fetchNuGet { pname = "System.Reflection"; version = "4.1.0"; sha256 = "1js89429pfw79mxvbzp8p3q93il6rdff332hddhzi5wqglc4gml9"; })
+  (fetchNuGet { pname = "System.Reflection"; version = "4.3.0"; sha256 = "0xl55k0mw8cd8ra6dxzh974nxif58s3k1rjv1vbd7gjbjr39j11m"; })
+  (fetchNuGet { pname = "System.Reflection.Emit"; version = "4.0.1"; sha256 = "0ydqcsvh6smi41gyaakglnv252625hf29f7kywy2c70nhii2ylqp"; })
+  (fetchNuGet { pname = "System.Reflection.Emit"; version = "4.3.0"; sha256 = "11f8y3qfysfcrscjpjym9msk7lsfxkk4fmz9qq95kn3jd0769f74"; })
+  (fetchNuGet { pname = "System.Reflection.Emit.ILGeneration"; version = "4.0.1"; sha256 = "1pcd2ig6bg144y10w7yxgc9d22r7c7ww7qn1frdfwgxr24j9wvv0"; })
+  (fetchNuGet { pname = "System.Reflection.Emit.ILGeneration"; version = "4.3.0"; sha256 = "0w1n67glpv8241vnpz1kl14sy7zlnw414aqwj4hcx5nd86f6994q"; })
+  (fetchNuGet { pname = "System.Reflection.Emit.Lightweight"; version = "4.0.1"; sha256 = "1s4b043zdbx9k39lfhvsk68msv1nxbidhkq6nbm27q7sf8xcsnxr"; })
+  (fetchNuGet { pname = "System.Reflection.Emit.Lightweight"; version = "4.3.0"; sha256 = "0ql7lcakycrvzgi9kxz1b3lljd990az1x6c4jsiwcacrvimpib5c"; })
+  (fetchNuGet { pname = "System.Reflection.Extensions"; version = "4.0.1"; sha256 = "0m7wqwq0zqq9gbpiqvgk3sr92cbrw7cp3xn53xvw7zj6rz6fdirn"; })
+  (fetchNuGet { pname = "System.Reflection.Extensions"; version = "4.3.0"; sha256 = "02bly8bdc98gs22lqsfx9xicblszr2yan7v2mmw3g7hy6miq5hwq"; })
+  (fetchNuGet { pname = "System.Reflection.Metadata"; version = "1.6.0"; sha256 = "1wdbavrrkajy7qbdblpbpbalbdl48q3h34cchz24gvdgyrlf15r4"; })
+  (fetchNuGet { pname = "System.Reflection.Primitives"; version = "4.0.1"; sha256 = "1bangaabhsl4k9fg8khn83wm6yial8ik1sza7401621jc6jrym28"; })
+  (fetchNuGet { pname = "System.Reflection.Primitives"; version = "4.3.0"; sha256 = "04xqa33bld78yv5r93a8n76shvc8wwcdgr1qvvjh959g3rc31276"; })
+  (fetchNuGet { pname = "System.Reflection.TypeExtensions"; version = "4.1.0"; sha256 = "1bjli8a7sc7jlxqgcagl9nh8axzfl11f4ld3rjqsyxc516iijij7"; })
+  (fetchNuGet { pname = "System.Reflection.TypeExtensions"; version = "4.3.0"; sha256 = "0y2ssg08d817p0vdag98vn238gyrrynjdj4181hdg780sif3ykp1"; })
+  (fetchNuGet { pname = "System.Resources.ResourceManager"; version = "4.0.1"; sha256 = "0b4i7mncaf8cnai85jv3wnw6hps140cxz8vylv2bik6wyzgvz7bi"; })
+  (fetchNuGet { pname = "System.Resources.ResourceManager"; version = "4.3.0"; sha256 = "0sjqlzsryb0mg4y4xzf35xi523s4is4hz9q4qgdvlvgivl7qxn49"; })
+  (fetchNuGet { pname = "System.Runtime"; version = "4.1.0"; sha256 = "02hdkgk13rvsd6r9yafbwzss8kr55wnj8d5c7xjnp8gqrwc8sn0m"; })
+  (fetchNuGet { pname = "System.Runtime"; version = "4.3.0"; sha256 = "066ixvgbf2c929kgknshcxqj6539ax7b9m570cp8n179cpfkapz7"; })
+  (fetchNuGet { pname = "System.Runtime.CompilerServices.Unsafe"; version = "4.4.0"; sha256 = "0a6ahgi5b148sl5qyfpyw383p3cb4yrkm802k29fsi4mxkiwir29"; })
+  (fetchNuGet { pname = "System.Runtime.CompilerServices.Unsafe"; version = "6.0.0"; sha256 = "0qm741kh4rh57wky16sq4m0v05fxmkjjr87krycf5vp9f0zbahbc"; })
+  (fetchNuGet { pname = "System.Runtime.Extensions"; version = "4.1.0"; sha256 = "0rw4rm4vsm3h3szxp9iijc3ksyviwsv6f63dng3vhqyg4vjdkc2z"; })
+  (fetchNuGet { pname = "System.Runtime.Extensions"; version = "4.3.0"; sha256 = "1ykp3dnhwvm48nap8q23893hagf665k0kn3cbgsqpwzbijdcgc60"; })
+  (fetchNuGet { pname = "System.Runtime.Handles"; version = "4.0.1"; sha256 = "1g0zrdi5508v49pfm3iii2hn6nm00bgvfpjq1zxknfjrxxa20r4g"; })
+  (fetchNuGet { pname = "System.Runtime.Handles"; version = "4.3.0"; sha256 = "0sw2gfj2xr7sw9qjn0j3l9yw07x73lcs97p8xfc9w1x9h5g5m7i8"; })
+  (fetchNuGet { pname = "System.Runtime.InteropServices"; version = "4.1.0"; sha256 = "01kxqppx3dr3b6b286xafqilv4s2n0gqvfgzfd4z943ga9i81is1"; })
+  (fetchNuGet { pname = "System.Runtime.InteropServices"; version = "4.3.0"; sha256 = "00hywrn4g7hva1b2qri2s6rabzwgxnbpw9zfxmz28z09cpwwgh7j"; })
+  (fetchNuGet { pname = "System.Runtime.InteropServices.RuntimeInformation"; version = "4.0.0"; sha256 = "0glmvarf3jz5xh22iy3w9v3wyragcm4hfdr17v90vs7vcrm7fgp6"; })
+  (fetchNuGet { pname = "System.Runtime.InteropServices.RuntimeInformation"; version = "4.3.0"; sha256 = "0q18r1sh4vn7bvqgd6dmqlw5v28flbpj349mkdish2vjyvmnb2ii"; })
+  (fetchNuGet { pname = "System.Runtime.Numerics"; version = "4.0.1"; sha256 = "1y308zfvy0l5nrn46mqqr4wb4z1xk758pkk8svbz8b5ij7jnv4nn"; })
+  (fetchNuGet { pname = "System.Runtime.Numerics"; version = "4.3.0"; sha256 = "19rav39sr5dky7afygh309qamqqmi9kcwvz3i0c5700v0c5cg61z"; })
+  (fetchNuGet { pname = "System.Security.Claims"; version = "4.3.0"; sha256 = "0jvfn7j22l3mm28qjy3rcw287y9h65ha4m940waaxah07jnbzrhn"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Algorithms"; version = "4.2.0"; sha256 = "148s9g5dgm33ri7dnh19s4lgnlxbpwvrw2jnzllq2kijj4i4vs85"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Algorithms"; version = "4.3.0"; sha256 = "03sq183pfl5kp7gkvq77myv7kbpdnq3y0xj7vi4q1kaw54sny0ml"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Cng"; version = "4.2.0"; sha256 = "118jijz446kix20blxip0f0q8mhsh9bz118mwc2ch1p6g7facpzc"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Cng"; version = "4.3.0"; sha256 = "1k468aswafdgf56ab6yrn7649kfqx2wm9aslywjam1hdmk5yypmv"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Cng"; version = "4.5.0"; sha256 = "1pm4ykbcz48f1hdmwpia432ha6qbb9kbrxrrp7cg3m8q8xn52ngn"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Csp"; version = "4.0.0"; sha256 = "1cwv8lqj8r15q81d2pz2jwzzbaji0l28xfrpw29kdpsaypm92z2q"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Csp"; version = "4.3.0"; sha256 = "1x5wcrddf2s3hb8j78cry7yalca4lb5vfnkrysagbn6r9x6xvrx1"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Encoding"; version = "4.0.0"; sha256 = "0a8y1a5wkmpawc787gfmnrnbzdgxmx1a14ax43jf3rj9gxmy3vk4"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Encoding"; version = "4.3.0"; sha256 = "1jr6w70igqn07k5zs1ph6xja97hxnb3mqbspdrff6cvssgrixs32"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.OpenSsl"; version = "4.0.0"; sha256 = "16sx3cig3d0ilvzl8xxgffmxbiqx87zdi8fc73i3i7zjih1a7f4q"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0givpvvj8yc7gv4lhb6s1prq6p2c4147204a0wib89inqzd87gqc"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Primitives"; version = "4.0.0"; sha256 = "0i7cfnwph9a10bm26m538h5xcr8b36jscp9sy1zhgifksxz4yixh"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.Primitives"; version = "4.3.0"; sha256 = "0pyzncsv48zwly3lw4f2dayqswcfvdwq2nz0dgwmi7fj3pn64wby"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.ProtectedData"; version = "8.0.0"; sha256 = "1ysjx3b5ips41s32zacf4vs7ig41906mxrsbmykdzi0hvdmjkgbx"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.X509Certificates"; version = "4.1.0"; sha256 = "0clg1bv55mfv5dq00m19cp634zx6inm31kf8ppbq1jgyjf2185dh"; })
+  (fetchNuGet { pname = "System.Security.Cryptography.X509Certificates"; version = "4.3.0"; sha256 = "0valjcz5wksbvijylxijjxb1mp38mdhv03r533vnx1q3ikzdav9h"; })
+  (fetchNuGet { pname = "System.Security.Principal"; version = "4.3.0"; sha256 = "12cm2zws06z4lfc4dn31iqv7072zyi4m910d4r6wm8yx85arsfxf"; })
+  (fetchNuGet { pname = "System.Security.Principal.Windows"; version = "4.3.0"; sha256 = "00a0a7c40i3v4cb20s2cmh9csb5jv2l0frvnlzyfxh848xalpdwr"; })
+  (fetchNuGet { pname = "System.Text.Encoding"; version = "4.0.11"; sha256 = "1dyqv0hijg265dwxg6l7aiv74102d6xjiwplh2ar1ly6xfaa4iiw"; })
+  (fetchNuGet { pname = "System.Text.Encoding"; version = "4.3.0"; sha256 = "1f04lkir4iladpp51sdgmis9dj4y8v08cka0mbmsy0frc9a4gjqr"; })
+  (fetchNuGet { pname = "System.Text.Encoding.Extensions"; version = "4.0.11"; sha256 = "08nsfrpiwsg9x5ml4xyl3zyvjfdi4mvbqf93kjdh11j4fwkznizs"; })
+  (fetchNuGet { pname = "System.Text.Encoding.Extensions"; version = "4.3.0"; sha256 = "11q1y8hh5hrp5a3kw25cb6l00v5l5dvirkz8jr3sq00h1xgcgrxy"; })
+  (fetchNuGet { pname = "System.Text.Encodings.Web"; version = "6.0.0"; sha256 = "06n9ql3fmhpjl32g3492sj181zjml5dlcc5l76xq2h38c4f87sai"; })
+  (fetchNuGet { pname = "System.Text.Encodings.Web"; version = "7.0.0"; sha256 = "1151hbyrcf8kyg1jz8k9awpbic98lwz9x129rg7zk1wrs6vjlpxl"; })
+  (fetchNuGet { pname = "System.Text.Encodings.Web"; version = "8.0.0"; sha256 = "1wbypkx0m8dgpsaqgyywz4z760xblnwalb241d5qv9kx8m128i11"; })
+  (fetchNuGet { pname = "System.Text.Json"; version = "6.0.2"; sha256 = "1lz6gx1r4if8sbx6yp9h0mi0g9ffr40x0cg518l0z2aiqgil3fk0"; })
+  (fetchNuGet { pname = "System.Text.Json"; version = "7.0.0"; sha256 = "0scb0lp7wbgcinaa4kqiqs7b8i5nx4ppfad81138jiwd1sl37pyp"; })
+  (fetchNuGet { pname = "System.Text.Json"; version = "8.0.0"; sha256 = "134savxw0sq7s448jnzw17bxcijsi1v38mirpbb6zfxmqlf04msw"; })
+  (fetchNuGet { pname = "System.Text.RegularExpressions"; version = "4.1.0"; sha256 = "1mw7vfkkyd04yn2fbhm38msk7dz2xwvib14ygjsb8dq2lcvr18y7"; })
+  (fetchNuGet { pname = "System.Text.RegularExpressions"; version = "4.3.0"; sha256 = "1bgq51k7fwld0njylfn7qc5fmwrk2137gdq7djqdsw347paa9c2l"; })
+  (fetchNuGet { pname = "System.Threading"; version = "4.0.11"; sha256 = "19x946h926bzvbsgj28csn46gak2crv2skpwsx80hbgazmkgb1ls"; })
+  (fetchNuGet { pname = "System.Threading"; version = "4.3.0"; sha256 = "0rw9wfamvhayp5zh3j7p1yfmx9b5khbf4q50d8k5rk993rskfd34"; })
+  (fetchNuGet { pname = "System.Threading.Channels"; version = "7.0.0"; sha256 = "1qrmqa6hpzswlmyp3yqsbnmia9i5iz1y208xpqc1y88b1f6j1v8a"; })
+  (fetchNuGet { pname = "System.Threading.Tasks"; version = "4.0.11"; sha256 = "0nr1r41rak82qfa5m0lhk9mp0k93bvfd7bbd9sdzwx9mb36g28p5"; })
+  (fetchNuGet { pname = "System.Threading.Tasks"; version = "4.3.0"; sha256 = "134z3v9abw3a6jsw17xl3f6hqjpak5l682k2vz39spj4kmydg6k7"; })
+  (fetchNuGet { pname = "System.Threading.Tasks.Extensions"; version = "4.0.0"; sha256 = "1cb51z062mvc2i8blpzmpn9d9mm4y307xrwi65di8ri18cz5r1zr"; })
+  (fetchNuGet { pname = "System.Threading.Tasks.Extensions"; version = "4.3.0"; sha256 = "1xxcx2xh8jin360yjwm4x4cf5y3a2bwpn2ygkfkwkicz7zk50s2z"; })
+  (fetchNuGet { pname = "System.Threading.Tasks.Extensions"; version = "4.5.4"; sha256 = "0y6ncasgfcgnjrhynaf0lwpkpkmv4a07sswwkwbwb5h7riisj153"; })
+  (fetchNuGet { pname = "System.Threading.ThreadPool"; version = "4.3.0"; sha256 = "027s1f4sbx0y1xqw2irqn6x161lzj8qwvnh2gn78ciiczdv10vf1"; })
+  (fetchNuGet { pname = "System.Threading.Timer"; version = "4.0.1"; sha256 = "15n54f1f8nn3mjcjrlzdg6q3520571y012mx7v991x2fvp73lmg6"; })
+  (fetchNuGet { pname = "System.Threading.Timer"; version = "4.3.0"; sha256 = "1nx773nsx6z5whv8kaa1wjh037id2f1cxhb69pvgv12hd2b6qs56"; })
+  (fetchNuGet { pname = "System.Xml.ReaderWriter"; version = "4.0.11"; sha256 = "0c6ky1jk5ada9m94wcadih98l6k1fvf6vi7vhn1msjixaha419l5"; })
+  (fetchNuGet { pname = "System.Xml.ReaderWriter"; version = "4.3.0"; sha256 = "0c47yllxifzmh8gq6rq6l36zzvw4kjvlszkqa9wq3fr59n0hl3s1"; })
+  (fetchNuGet { pname = "System.Xml.XDocument"; version = "4.0.11"; sha256 = "0n4lvpqzy9kc7qy1a4acwwd7b7pnvygv895az5640idl2y9zbz18"; })
+  (fetchNuGet { pname = "System.Xml.XDocument"; version = "4.3.0"; sha256 = "08h8fm4l77n0nd4i4fk2386y809bfbwqb7ih9d7564ifcxr5ssxd"; })
+  (fetchNuGet { pname = "System.Xml.XmlDocument"; version = "4.3.0"; sha256 = "0bmz1l06dihx52jxjr22dyv5mxv6pj4852lx68grjm7bivhrbfwi"; })
+  (fetchNuGet { pname = "TagLibSharp"; version = "2.3.0"; sha256 = "1z7v9lrkss1f8s42sclsq3az9zjihgmhyxnwhjyf0scgk1amngrw"; })
+  (fetchNuGet { pname = "Utility.CommandLine.Arguments"; version = "6.0.0"; sha256 = "0i8m0vn1wm4wy7d3radyha6kxg0l50r2q02zlmkg6633yyiqry1a"; })
+  (fetchNuGet { pname = "Utility.EnvironmentVariables"; version = "1.0.5"; sha256 = "1x9vd5qni194yxc18pcrnvln9zib01sgai7ygw86zcj5137hj72i"; })
+  (fetchNuGet { pname = "xunit"; version = "2.6.3"; sha256 = "0yy0579ipqk4fab877kc0y947q9i83329rwwf47apwgbhpkcfi62"; })
+  (fetchNuGet { pname = "xunit.abstractions"; version = "2.0.1"; sha256 = "0c7zkf3i8n1mhc457q859klk067bw1xbf31lyxlwc5hlx9aqz65z"; })
+  (fetchNuGet { pname = "xunit.abstractions"; version = "2.0.3"; sha256 = "00wl8qksgkxld76fgir3ycc5rjqv1sqds6x8yx40927q5py74gfh"; })
+  (fetchNuGet { pname = "xunit.analyzers"; version = "1.7.0"; sha256 = "0dga1c6icksd6y7c652pkwcmdsqxrgnxj3v2nijc0vayqa5prnvc"; })
+  (fetchNuGet { pname = "xunit.assert"; version = "2.6.3"; sha256 = "0i4g5sw0j2j4ajya671d4ragq3xrgpaf2bw5fzs7hlkykm0s5vgc"; })
+  (fetchNuGet { pname = "xunit.core"; version = "2.6.3"; sha256 = "14jissxdzrshnrz8rbgxzvn93if808fvmcbha6bz9f5yh503z88p"; })
+  (fetchNuGet { pname = "xunit.extensibility.core"; version = "2.2.0"; sha256 = "0l9fl09l709dq671r5yvmcrk9vhxgszmxf3ny1h9ja2sp9xx5pbs"; })
+  (fetchNuGet { pname = "xunit.extensibility.core"; version = "2.6.3"; sha256 = "1j9hjrar5lr3irxmpnbk564dc4g11hkjx6w4241xx333pz4h8jr5"; })
+  (fetchNuGet { pname = "xunit.extensibility.execution"; version = "2.6.3"; sha256 = "0514n70rizl96kx9b62qpsia2nc7k9rjbmwn32vbclpvil2jdy07"; })
+  (fetchNuGet { pname = "xunit.runner.visualstudio"; version = "2.5.5"; sha256 = "06w2skg7vn1wag7x06z8gw2rbfzq21i3alg6dfcwj0rkq98zyxac"; })
+  (fetchNuGet { pname = "YamlDotNet"; version = "13.7.1"; sha256 = "1m2lnfb2r8382fpjyxp79wnbis7l462zksj3618142q53y33bk5z"; })
+]
diff --git a/nixpkgs/pkgs/servers/web-apps/sogo/default.nix b/nixpkgs/pkgs/servers/web-apps/sogo/default.nix
new file mode 100644
index 000000000000..ab617dc291b2
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/sogo/default.nix
@@ -0,0 +1,83 @@
+{ gnustep, lib, fetchFromGitHub, fetchpatch, makeWrapper, python3, lndir, libxcrypt
+, openssl, openldap, sope, libmemcached, curl, libsodium, libytnef, libzip, pkg-config, nixosTests
+, oath-toolkit
+, enableActiveSync ? false
+, libwbxml }:
+gnustep.stdenv.mkDerivation rec {
+  pname = "SOGo";
+  version = "5.9.1";
+
+  # always update the sope package as well, when updating sogo
+  src = fetchFromGitHub {
+    owner = "inverse-inc";
+    repo = pname;
+    rev = "SOGo-${version}";
+    hash = "sha256-b6BZZ61wY0Akt1Q6+Bq6JXAx/67MwBNbzHr3sB0NuRg=";
+  };
+
+  nativeBuildInputs = [ gnustep.make makeWrapper python3 pkg-config ];
+  buildInputs = [ gnustep.base sope openssl libmemcached curl libsodium libytnef libzip openldap oath-toolkit libxcrypt ]
+    ++ lib.optional enableActiveSync libwbxml;
+
+  patches = lib.optional enableActiveSync ./enable-activesync.patch;
+
+  postPatch = ''
+    # Exclude NIX_ variables
+    sed -i 's/grep GNUSTEP_/grep ^GNUSTEP_/g' configure
+
+    # Disable argument verification because $out is not a GNUStep prefix
+    sed -i 's/^validateArgs$//g' configure
+
+    # Patch exception-generating python scripts
+    patchShebangs .
+
+    # Move all GNUStep makefiles to a common directory
+    mkdir -p makefiles
+    cp -r {${gnustep.make},${sope}}/share/GNUstep/Makefiles/* makefiles
+
+    # Modify the search path for GNUStep makefiles
+    find . -type f -name GNUmakefile -exec sed -i "s:\\$.GNUSTEP_MAKEFILES.:$PWD/makefiles:g" {} +
+  '';
+
+  configureFlags = [
+    "--disable-debug"
+    "--with-ssl=ssl"
+    "--enable-mfa"
+  ];
+
+  env.NIX_CFLAGS_COMPILE = "-Wno-error=incompatible-pointer-types -Wno-error=int-conversion -Wno-error=implicit-int";
+
+  preFixup = ''
+    # Create gnustep.conf
+    mkdir -p $out/share/GNUstep
+    cp ${gnustep.make}/etc/GNUstep/GNUstep.conf $out/share/GNUstep/
+    sed -i "s:${gnustep.make}:$out:g" $out/share/GNUstep/GNUstep.conf
+
+    # Link in GNUstep base
+    ${lndir}/bin/lndir ${lib.getLib gnustep.base}/lib/GNUstep/ $out/lib/GNUstep/
+
+    # Link in sope
+    ${lndir}/bin/lndir ${sope}/ $out/
+
+    # sbin fixup
+    mkdir -p $out/bin
+    mv $out/sbin/* $out/bin
+    rmdir $out/sbin
+
+    # Make sogo find its files
+    for bin in $out/bin/*; do
+      wrapProgram $bin --prefix LD_LIBRARY_PATH : $out/lib/sogo --prefix GNUSTEP_CONFIG_FILE : $out/share/GNUstep/GNUstep.conf
+    done
+  '';
+
+  passthru.tests.sogo = nixosTests.sogo;
+
+  meta = with lib; {
+    description = "A very fast and scalable modern collaboration suite (groupware)";
+    license = with licenses; [ gpl2Only lgpl21Only ];
+    homepage = "https://sogo.nu/";
+    platforms = platforms.linux;
+    maintainers = with maintainers; [];
+  };
+}
+
diff --git a/nixpkgs/pkgs/servers/web-apps/sogo/enable-activesync.patch b/nixpkgs/pkgs/servers/web-apps/sogo/enable-activesync.patch
new file mode 100644
index 000000000000..2c2aba26a211
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/sogo/enable-activesync.patch
@@ -0,0 +1,21 @@
+--- a/ActiveSync/NSData+ActiveSync.m
++++ b/ActiveSync/NSData+ActiveSync.m
+@@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ #import <NGExtensions/NGBase64Coding.h>
+ #import <NGExtensions/NSObject+Logs.h>
+ 
+-#include <wbxml/wbxml.h>
++#include <libwbxml-1.0/wbxml/wbxml.h>
+ 
+ #define WBXMLDEBUG 0
+ 
+--- a/GNUmakefile
++++ b/GNUmakefile
+@@ -11,6 +11,7 @@ SUBPROJECTS = \
+ 	UI		\
+ 	Tools		\
+ 	Tests/Unit	\
++	ActiveSync	\
+ 
+ 
+ include $(GNUSTEP_MAKEFILES)/aggregate.make
diff --git a/nixpkgs/pkgs/servers/web-apps/wallabag/default.nix b/nixpkgs/pkgs/servers/web-apps/wallabag/default.nix
new file mode 100644
index 000000000000..792292066f53
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wallabag/default.nix
@@ -0,0 +1,57 @@
+{ lib
+, stdenv
+, fetchurl
+}:
+
+# Point the environment variable $WALLABAG_DATA to a data directory
+# that contains the folder `app` which must be a clone of
+# wallabag's configuration files with your customized `parameters.yml`.
+# In practice you need to copy `${pkgs.wallabag}/app` and the
+# customizzed `parameters.yml` to $WALLABAG_DATA.
+# These need to be updated every package upgrade.
+#
+# After a package upgrade, empty the `var/cache` folder or unexpected
+# error will occur.
+
+let
+  pname = "wallabag";
+  version = "2.6.8";
+in
+stdenv.mkDerivation {
+  inherit pname version;
+
+  # Release tarball includes vendored files
+  src = fetchurl {
+    url = "https://github.com/wallabag/wallabag/releases/download/${version}/wallabag-${version}.tar.gz";
+    hash = "sha256-pmQXafqpd5rTwBIYG9NnwIIPta6Ek7iYaPaHvz1s550=";
+  };
+
+  patches = [
+    ./wallabag-data.patch # exposes $WALLABAG_DATA
+  ];
+
+  dontBuild = true;
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir $out
+    cp -R * $out/
+
+    runHook postInstall
+  '';
+
+  meta = with lib; {
+    description = "wallabag is a self hostable application for saving web pages";
+    longDescription = ''
+      wallabag is a self-hostable PHP application allowing you to not
+      miss any content anymore. Click, save and read it when you can.
+      It extracts content so that you can read it when you have time.
+    '';
+    license = licenses.mit;
+    homepage = "http://wallabag.org";
+    changelog = "https://github.com/wallabag/wallabag/releases/tag/${version}";
+    maintainers = with maintainers; [ schneefux ];
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/wallabag/wallabag-data.patch b/nixpkgs/pkgs/servers/web-apps/wallabag/wallabag-data.patch
new file mode 100644
index 000000000000..4276af58c584
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wallabag/wallabag-data.patch
@@ -0,0 +1,26 @@
+diff --git a/app/AppKernel.php b/app/AppKernel.php
+index 61b734e06..d25d1aaa3 100644
+--- a/app/AppKernel.php
++++ b/app/AppKernel.php
+@@ -62,14 +62,19 @@ class AppKernel extends Kernel
+         return $bundles;
+     }
+ 
++    public function getProjectDir()
++    {
++        return getenv('WALLABAG_DATA') ?: dirname(__DIR__);
++    }
++
+     public function getCacheDir()
+     {
+-        return dirname(__DIR__) . '/var/cache/' . $this->getEnvironment();
++        return $this->getProjectDir() . '/var/cache/' . $this->getEnvironment();
+     }
+ 
+     public function getLogDir()
+     {
+-        return dirname(__DIR__) . '/var/logs';
++        return $this->getProjectDir() . '/var/logs';
+     }
+ 
+     public function registerContainerConfiguration(LoaderInterface $loader)
diff --git a/nixpkgs/pkgs/servers/web-apps/whitebophir/default.nix b/nixpkgs/pkgs/servers/web-apps/whitebophir/default.nix
new file mode 100644
index 000000000000..b3401ff78fc7
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/whitebophir/default.nix
@@ -0,0 +1,49 @@
+{ lib
+, buildNpmPackage
+, fetchFromGitHub
+, nodejs_20
+, runtimeShell
+}:
+
+let
+  nodejs = nodejs_20;
+in buildNpmPackage rec {
+  pname = "whitebophir";
+  version = "1.19.1";
+
+  src = fetchFromGitHub {
+    owner = "lovasoa";
+    repo = "whitebophir";
+    rev = "v${version}";
+    hash = "sha256-4T7s9WrpyHVPcw0QY0C0sczDJYKzA4bAAfEv8q2pOy4=";
+  };
+
+  inherit nodejs;
+
+  npmDepsHash = "sha256-mKDkkX7vWrnfEg1D65bqn/MtyUS0DKjTtkDW6ebso7g=";
+
+  # geckodriver tries to access network
+  npmFlags = [ "--ignore-scripts" ];
+
+  dontNpmBuild = true;
+
+  postInstall = ''
+    out_whitebophir=$out/lib/node_modules/whitebophir
+
+    mkdir $out/bin
+    cat <<EOF > $out/bin/whitebophir
+    #!${runtimeShell}
+    exec ${nodejs}/bin/node $out_whitebophir/server/server.js
+    EOF
+    chmod +x $out/bin/whitebophir
+  '';
+
+  meta = with lib; {
+    description = "Online collaborative whiteboard that is simple, free, easy to use and to deploy";
+    license = licenses.agpl3Plus;
+    homepage = "https://github.com/lovasoa/whitebophir";
+    mainProgram = "whitebophir";
+    maintainers = with maintainers; [ iblech ];
+    platforms = platforms.unix;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/wiki-js/default.nix b/nixpkgs/pkgs/servers/web-apps/wiki-js/default.nix
new file mode 100644
index 000000000000..2c3934805436
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wiki-js/default.nix
@@ -0,0 +1,35 @@
+{ stdenv, fetchurl, lib, nixosTests, jq, moreutils }:
+
+stdenv.mkDerivation rec {
+  pname = "wiki-js";
+  version = "2.5.301";
+
+  src = fetchurl {
+    url = "https://github.com/Requarks/wiki/releases/download/v${version}/${pname}.tar.gz";
+    sha256 = "sha256-E1XXq4xzExOqBHjgvfVnZ9z8qH1/99ku53KYwQYe7kM=";
+  };
+
+  sourceRoot = ".";
+
+  dontBuild = true;
+  installPhase = ''
+    runHook preInstall
+
+    mkdir $out
+    cp -r . $out
+
+    runHook postInstall
+  '';
+
+  passthru = {
+    tests = { inherit (nixosTests) wiki-js; };
+    updateScript = ./update.sh;
+  };
+
+  meta = with lib; {
+    homepage = "https://js.wiki/";
+    description = "A modern and powerful wiki app built on Node.js";
+    license = licenses.agpl3Only;
+    maintainers = with maintainers; [ ma27 ];
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/wiki-js/update.sh b/nixpkgs/pkgs/servers/web-apps/wiki-js/update.sh
new file mode 100755
index 000000000000..63015800e691
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wiki-js/update.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env nix-shell
+#!nix-shell -i bash -p curl common-updater-scripts
+
+oldVersion="$(nix-instantiate --eval -E "with import ./. {}; lib.getVersion wiki-js" | tr -d '"')"
+latestTag="$(git ls-remote --tags --sort="v:refname" https://github.com/Requarks/wiki.git | tail -1 | awk '{ print $2 }' | sed -E "s,^refs/tags/v(.*)$,\1,")"
+
+targetVersion="${1:-$latestTag}"
+if [ ! "${oldVersion}" = "${targetVersion}" ]; then
+  update-source-version wiki-js "${targetVersion}"
+  nix-build -A wiki-js
+else
+  echo "wiki-js is already up-to-date"
+fi
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/default.nix b/nixpkgs/pkgs/servers/web-apps/wordpress/default.nix
new file mode 100644
index 000000000000..f1a73feab865
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/default.nix
@@ -0,0 +1,11 @@
+{ callPackage }: builtins.mapAttrs (_: callPackage ./generic.nix) rec {
+  wordpress = wordpress6_4;
+  wordpress6_3 = {
+    version = "6.3.2";
+    hash = "sha256-Jo2/Vlm4Ml24ucPI6ZHs2mkbpY2rZB1dofmGXNPweA8=";
+  };
+  wordpress6_4 = {
+    version = "6.4.3";
+    hash = "sha256-PwjHHRlwhEH9q94bPq34NnQv3uhm1kOpjRAu0/ECaYY=";
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/generic.nix b/nixpkgs/pkgs/servers/web-apps/wordpress/generic.nix
new file mode 100644
index 000000000000..d2d97dab35d9
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/generic.nix
@@ -0,0 +1,49 @@
+{ lib, version, hash, stdenv, fetchurl, nixosTests, writeScript }:
+
+stdenv.mkDerivation rec {
+  pname = "wordpress";
+  inherit version;
+
+  src = fetchurl {
+    url = "https://wordpress.org/${pname}-${version}.tar.gz";
+    inherit hash;
+  };
+
+  installPhase = ''
+    runHook preInstall
+
+    # remove non-essential plugins and themes
+    rm -r wp-content/{plugins,themes}
+    mkdir wp-content/plugins
+    cat << EOF > wp-content/plugins/index.php
+    <?php
+    // Silence is golden.
+    EOF
+    cp -a wp-content/{plugins,themes}
+
+    mkdir -p $out/share/wordpress
+    cp -r . $out/share/wordpress
+
+    runHook postInstall
+  '';
+
+  passthru.tests = {
+    inherit (nixosTests) wordpress;
+  };
+
+  passthru.updateScript = writeScript "update.sh" ''
+    #!/usr/bin/env nix-shell
+    #!nix-shell -i bash -p common-updater-scripts jq
+    set -eu -o pipefail
+    version=$(curl --globoff "https://api.wordpress.org/core/version-check/1.7/" | jq -r '.offers[0].version')
+    update-source-version wordpress $version
+  '';
+
+  meta = with lib; {
+    homepage = "https://wordpress.org";
+    description = "WordPress is open source software you can use to create a beautiful website, blog, or app";
+    license = [ licenses.gpl2 ];
+    maintainers = [ maintainers.basvandijk ];
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/packages/README.md b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/README.md
new file mode 100644
index 000000000000..6ca50e1d9c4a
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/README.md
@@ -0,0 +1,46 @@
+= Adding plugin, theme or language =
+
+To extend the wordpressPackages set, add a new line to the corresponding json
+file with the codename of the package:
+
+- `wordpress-languages.json` for language packs
+- `wordpress-themes.json` for themes
+- `wordpress-plugins.json` for plugins
+
+The codename is the last part in the url of the plugin or theme page, for
+example `cookie-notice` in in the url
+`https://wordpress.org/plugins/cookie-notice/` or `twentytwenty` in
+`https://wordpress.org/themes/twentytwenty/`.
+
+In case of language packages, the name consists of country and language codes.
+For example `de_DE` for country code `de` (Germany) and language `DE` (German).
+For available translations and language codes see [upstream translation repository](https://translate.wordpress.org).
+
+To regenerate the nixpkgs wordpressPackages set, run:
+
+```
+./generate.sh
+```
+
+After that you can commit and submit the changes.
+
+= Usage with the Wordpress module =
+
+The plugins will be available in the namespace `wordpressPackages.plugins`.
+Using it together with the Wordpress module could look like this:
+
+```
+services.wordpress = {
+  sites."blog.${config.networking.domain}" = {
+    plugins = with pkgs.wordpressPackages.plugins; [
+      anti-spam-bee
+      code-syntax-block
+      cookie-notice
+      lightbox-with-photoswipe
+      wp-gdpr-compliance
+    ];
+  };
+};
+```
+
+The same scheme applies to `themes` and `languages`.
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/packages/default.nix b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/default.nix
new file mode 100644
index 000000000000..cce6897cb919
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/default.nix
@@ -0,0 +1,95 @@
+# Source: https://git.helsinki.tools/helsinki-systems/wp4nix/-/blob/master/default.nix
+# Licensed under: MIT
+# Slightly modified
+
+{ lib, newScope, plugins, themes, languages, callPackage }:
+
+let packages = self:
+  let
+    generatedJson = {
+      inherit plugins themes languages;
+    };
+    sourceJson = {
+      plugins = builtins.fromJSON (builtins.readFile ./wordpress-plugins.json);
+      themes = builtins.fromJSON (builtins.readFile ./wordpress-themes.json);
+      languages = builtins.fromJSON (builtins.readFile ./wordpress-languages.json);
+    };
+
+  in {
+    # Create a generic WordPress package. Most arguments are just passed
+    # to `mkDerivation`. The version is automatically filtered for weird characters.
+    mkWordpressDerivation = self.callPackage ({ stdenvNoCC, lib, filterWPString, gettext, wp-cli }:
+      { type, pname, version, license, ... }@args:
+        assert lib.any (x: x == type) [ "plugin" "theme" "language" ];
+        stdenvNoCC.mkDerivation ({
+          pname = "wordpress-${type}-${pname}";
+          version = filterWPString version;
+
+          dontConfigure = true;
+          dontBuild = true;
+
+          installPhase = ''
+            runHook preInstall
+            cp -R ./. $out
+            runHook postInstall
+          '';
+
+          passthru = {
+            wpName = pname;
+          };
+
+          meta = {
+            license = lib.licenses.${license};
+          } // (args.passthru or {});
+        } // lib.optionalAttrs (type == "language") {
+          nativeBuildInputs = [ gettext wp-cli ];
+          dontBuild = false;
+          buildPhase = ''
+            runHook preBuild
+
+            find -name '*.po' -print0 | while IFS= read -d "" -r po; do
+              msgfmt -o $(basename "$po" .po).mo "$po"
+            done
+            wp i18n make-json .
+            rm *.po
+
+            runHook postBuild
+          '';
+        } // removeAttrs args [ "type" "pname" "version" "passthru" ])) {};
+
+    # Create a derivation from the official wordpress.org packages.
+    # This takes the type, the pname and the data generated from the go tool.
+    mkOfficialWordpressDerivation = self.callPackage ({ mkWordpressDerivation, fetchWordpress }:
+      { type, pname, data, license }:
+      mkWordpressDerivation {
+        inherit type pname license;
+        version = data.version;
+
+        src = fetchWordpress type data;
+      }) {};
+
+    # Filter out all characters that might occur in a version string but that that are not allowed
+    # in store paths.
+    filterWPString = builtins.replaceStrings [ " " "," "/" "&" ";" ''"'' "'" "$" ":" "(" ")" "[" "]" "{" "}" "|" "*" "\t" ] [ "_" "." "." "" "" "" "" "" "" "" "" "" "" "" "" "-" "" "" ];
+
+    # Fetch a package from the official wordpress.org SVN.
+    # The data supplied is the data straight from the go tool.
+    fetchWordpress = self.callPackage ({ fetchsvn }: type: data: fetchsvn {
+      inherit (data) rev sha256;
+      url = if type == "plugin" || type == "theme" then
+        "https://" + type + "s.svn.wordpress.org/" + data.path
+      else if type == "language" then
+        "https://i18n.svn.wordpress.org/core/" + data.version + "/" + data.path
+      else if type == "pluginLanguage" then
+        "https://i18n.svn.wordpress.org/plugins/" + data.path
+      else if type == "themeLanguage" then
+        "https://i18n.svn.wordpress.org/themes/" + data.path
+      else
+        throw "fetchWordpress: invalid package type ${type}";
+    }) {};
+
+  } // lib.mapAttrs (
+    type: pkgs: lib.makeExtensible (_: lib.mapAttrs (pname: data: self.mkOfficialWordpressDerivation {type = lib.removeSuffix "s" type; inherit pname data; license = sourceJson.${type}.${pname}; }) pkgs)) generatedJson;
+
+# This creates an extensible scope.
+in lib.recursiveUpdate ((lib.makeExtensible (_: (lib.makeScope newScope packages))).extend (selfWP: superWP: {})) (callPackage ./thirdparty.nix {})
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/packages/generate.sh b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/generate.sh
new file mode 100755
index 000000000000..0abf3e341a41
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/generate.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env nix-shell
+#!nix-shell -i bash -p wp4nix jq
+
+set -e
+set -u
+set -o pipefail
+set -x
+
+cd $(dirname "$0")
+
+nixFlags="--option experimental-features nix-command eval --raw --impure --expr"
+export NIX_PATH=nixpkgs=../../../../..
+export WP_VERSION=$(nix $nixFlags '(import <nixpkgs> {}).wordpress.version')
+
+PLUGINS=`cat wordpress-plugins.json | jq -r 'keys|.[]' | sed -z 's/\n/,/g;s/,$/\n/'`
+THEMES=`cat wordpress-themes.json | jq -r 'keys|.[]' | sed -z 's/\n/,/g;s/,$/\n/'`
+LANGUAGES=`cat wordpress-languages.json | jq -r 'keys|.[]' | sed -z 's/\n/,/g;s/,$/\n/'`
+
+wp4nix -p $PLUGINS -pl en
+wp4nix -t $THEMES -tl en
+wp4nix -l $LANGUAGES
+
+rm *.log themeLanguages.json pluginLanguages.json
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/packages/languages.json b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/languages.json
new file mode 100644
index 000000000000..6a9d4361f226
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/languages.json
@@ -0,0 +1,20 @@
+{
+  "de_DE": {
+    "path": "de_DE",
+    "rev": "1286009",
+    "sha256": "1w6q2ja1y77yagg73zhrw94f2vpgd521zahwhvxqxa8isphbrybj",
+    "version": "6.4"
+  },
+  "fr_FR": {
+    "path": "fr_FR",
+    "rev": "1285884",
+    "sha256": "1qlq7p9pmspizbgjp895jldb6cbsvfal6h02p44r87ag356cjk6j",
+    "version": "6.4"
+  },
+  "ro_RO": {
+    "path": "ro_RO",
+    "rev": "1296680",
+    "sha256": "0m98iaai240yn4lx4lhqgzi2wlxkz67v1cg86jhfi72n0rhr4l46",
+    "version": "6.4"
+  }
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/packages/plugins.json b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/plugins.json
new file mode 100644
index 000000000000..e85bf69310c1
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/plugins.json
@@ -0,0 +1,218 @@
+{
+  "add-widget-after-content": {
+    "path": "add-widget-after-content/tags/2.4.6",
+    "rev": "3003516",
+    "sha256": "1nqhx66fy82mwcnfg0r9v2mb6q2nnmhxy9j2451rphxhlxxjf1bf",
+    "version": "2.4.6"
+  },
+  "akismet": {
+    "path": "akismet/tags/5.3",
+    "rev": "2991242",
+    "sha256": "1i7y09x2aikndf80wl7xv65m71nv5s0w6jcadpp0dsyzp2m3gjnn",
+    "version": "5.3"
+  },
+  "antispam-bee": {
+    "path": "antispam-bee/tags/2.11.5",
+    "rev": "2969611",
+    "sha256": "1pbigfchwkz9zks3vf1xd83d0aj4n1fmlimn8dpa5pw96687nc9d",
+    "version": "2.11.5"
+  },
+  "async-javascript": {
+    "path": "async-javascript/tags/2.21.08.31",
+    "rev": "2929532",
+    "sha256": "0v9lrbxcgk6diz927q36nx45nbl6hm8bdig9lc0gj42i183y3g61",
+    "version": "2.21.08.31"
+  },
+  "breeze": {
+    "path": "breeze/tags/2.1.2",
+    "rev": "3011880",
+    "sha256": "164sf180j99icn39215s997qqmqddyqnkf7k29fwpkgz5ww0zkkd",
+    "version": "2.1.2"
+  },
+  "co-authors-plus": {
+    "path": "co-authors-plus/tags/3.5.15",
+    "rev": "2959167",
+    "sha256": "1n01sk2vgiym25wvxi4igpx773ph59y5f5lvwaasilamdpw0lzh4",
+    "version": "3.5.15"
+  },
+  "code-syntax-block": {
+    "path": "code-syntax-block/tags/3.1.1",
+    "rev": "2747615",
+    "sha256": "0dqdsl7f3ihshvly6cqd5l4cbimx5skmips514wvifspwggwmmjm",
+    "version": "3.1.1"
+  },
+  "cookie-notice": {
+    "path": "cookie-notice/tags/2.4.13",
+    "rev": "3002920",
+    "sha256": "0rw511zygmg1i8zp388s4fc526wr4pgszsqxw0bmwia6sjz0a9pn",
+    "version": "2.4.13"
+  },
+  "disable-xml-rpc": {
+    "path": "disable-xml-rpc/tags/1.0.1",
+    "rev": "2954460",
+    "sha256": "03vay6j7ac44pg55hlm02lglm3ggmjxdq95dhh0cmavbiafimhqq",
+    "version": "1.0.1"
+  },
+  "embed-extended": {
+    "path": "embed-extended/tags/1.4.0",
+    "rev": "2982701",
+    "sha256": "1qfxy9rp6ipp6r6m70vr30clbm2akssra4jbk8fss3qiz85rmfxa",
+    "version": "1.4.0"
+  },
+  "gutenberg": {
+    "path": "gutenberg/tags/17.3.0",
+    "rev": "3012944",
+    "sha256": "0n51lldbbk0sfzcjk8mcjnaj6dmhhbg45kc9a03igl6cnppw6g53",
+    "version": "17.3.0"
+  },
+  "hello-dolly": {
+    "path": "hello-dolly/tags/1.7.2",
+    "rev": "2807593",
+    "sha256": "0zzbzdkzpgc65djn3694li82zc2q25q3zzv0kqjr7zwqmnrli0jp",
+    "version": "1.7.2"
+  },
+  "hkdev-maintenance-mode": {
+    "path": "hkdev-maintenance-mode/trunk",
+    "rev": "3003933",
+    "sha256": "1mfn9njy7sp23hgpd597y74gs52gi9lm8qajv7xbgza82920mlgd",
+    "version": "2.5.0"
+  },
+  "jetpack": {
+    "path": "jetpack/tags/12.9.3",
+    "rev": "3013460",
+    "sha256": "1lgkd3bgaqf155a39zfxx7ikmfxpzfsfak71mrlga12sfmyrrw74",
+    "version": "12.9.3"
+  },
+  "jetpack-lite": {
+    "path": "jetpack-lite/tags/3.0.3",
+    "rev": "1895157",
+    "sha256": "04wq8cnhzgzrhm5pjwicsnavc46n6wdmb6xf8gz4wwl1di2hl471",
+    "version": "3.0.3"
+  },
+  "lightbox-photoswipe": {
+    "path": "lightbox-photoswipe/tags/5.1.0",
+    "rev": "3001652",
+    "sha256": "1mdrxc15skbg8gm18b88hj97mps668in7xvyvymfn5sgpf843glz",
+    "version": "5.1.0"
+  },
+  "login-lockdown": {
+    "path": "login-lockdown/tags/2.08",
+    "rev": "3007562",
+    "sha256": "0s9ahqbqcl0rlbbszrbdggyhnqw8k60xzlwq3nzsh2dxaphnmbi5",
+    "version": "2.08"
+  },
+  "mailpoet": {
+    "path": "mailpoet/tags/4.40.0",
+    "rev": "3008786",
+    "sha256": "18604065zjwdrr63ad0a8zqy0cdfh8f5i3jyq5na5iayspgmy0lz",
+    "version": "4.40.0"
+  },
+  "merge-minify-refresh": {
+    "path": "merge-minify-refresh/trunk",
+    "rev": "3007859",
+    "sha256": "1f9ppjkpza5h6z23ma7x9lrpqsq5qxc0n8zfffs44njf086n7k4f",
+    "version": "2.7"
+  },
+  "opengraph": {
+    "path": "opengraph/tags/1.11.2",
+    "rev": "2995321",
+    "sha256": "03cg7jm0g3rfwkvgjcg392mw09mlbmnvhw261rlldycfglmi270m",
+    "version": "1.11.2"
+  },
+  "simple-login-captcha": {
+    "path": "simple-login-captcha/tags/1.3.5",
+    "rev": "2988106",
+    "sha256": "1byq8f5qkxxnhjc4dk1ab7h8vzcr01y1nid81wwj2k1i03z9llqa",
+    "version": "1.3.5"
+  },
+  "simple-mastodon-verification": {
+    "path": "simple-mastodon-verification/tags/1.1.3",
+    "rev": "2998678",
+    "sha256": "0ikymrf21l86gpdcjfawadqg1nbfsm6gggcc1g2g553pjg277grz",
+    "version": "1.1.3"
+  },
+  "static-mail-sender-configurator": {
+    "path": "static-mail-sender-configurator/tags/0.10.0",
+    "rev": "2941521",
+    "sha256": "1mrwgqp1ril54xqr8k2gwgjcsbf4xv3671v15xawapwz730h2c4r",
+    "version": "0.10.0"
+  },
+  "tc-custom-javascript": {
+    "path": "tc-custom-javascript/tags/1.2.3",
+    "rev": "2870386",
+    "sha256": "0lcprrnf25p6a12mf5hkfnl6r470n35pgfdl9nizjh4q43qzdcam",
+    "version": "1.2.3"
+  },
+  "webp-converter-for-media": {
+    "path": "webp-converter-for-media/tags/5.11.5",
+    "rev": "3006520",
+    "sha256": "1mkfki9148w43r3h8afp1j8vkrljsch68y8l4m6i8w5jsjvb5c18",
+    "version": "5.11.5"
+  },
+  "webp-express": {
+    "path": "webp-express/tags/0.25.8",
+    "rev": "2981697",
+    "sha256": "17v94im2cnvjiglfzbqq598blwn7m5j84sd8ysbq8lc60kwn0vi3",
+    "version": "0.25.8"
+  },
+  "wordpress-seo": {
+    "path": "wordpress-seo/tags/21.7",
+    "rev": "3008568",
+    "sha256": "1iigdycbxhdzrprnajw54b1jjmp8akig72z9v78infaf2sjawmgh",
+    "version": "21.7"
+  },
+  "worker": {
+    "path": "worker/tags/4.9.18",
+    "rev": "3010154",
+    "sha256": "1wkkabw0g2c9bfqwqddjqrc13wwf39h508bb25cxwz2yi5fdhp9v",
+    "version": "4.9.18"
+  },
+  "wp-change-email-sender": {
+    "path": "wp-change-email-sender/trunk",
+    "rev": "2812298",
+    "sha256": "1ibdj2yv572pk21pr313pdrqxi2f9vawwd0byb0s38224jjx4plh",
+    "version": "1.0"
+  },
+  "wp-fastest-cache": {
+    "path": "wp-fastest-cache/tags/1.2.2",
+    "rev": "2994820",
+    "sha256": "1mj18yrljjdrd07b0yjkd9pwdciyn4jyrs6hgx6jcys0mc5p009v",
+    "version": "1.2.2"
+  },
+  "wp-gdpr-compliance": {
+    "path": "wp-gdpr-compliance/tags/2.0.22",
+    "rev": "2865556",
+    "sha256": "0zgn3pg2zhqqv89rl6pqwd3p3hvspsnn47iab7xw0d79nby0nh7c",
+    "version": "2.0.22"
+  },
+  "wp-mail-smtp": {
+    "path": "wp-mail-smtp/tags/3.11.0",
+    "rev": "3009463",
+    "sha256": "1vk6bdchqka5nmiakq9s8kj7psk2nq2yxln377bidqyqj0q9kqmk",
+    "version": "3.11.0"
+  },
+  "wp-statistics": {
+    "path": "wp-statistics/tags/14.3.2",
+    "rev": "3013471",
+    "sha256": "03iahbjnyyy1lxvxmfgzzzin0sfng0dyagx0q0bvfa9bqx4pi37h",
+    "version": "14.3.2"
+  },
+  "wp-swiper": {
+    "path": "wp-swiper/trunk",
+    "rev": "3013138",
+    "sha256": "1h5l99m73z7fn0l5sa4qbdpi3r8nanvrbciix5756qj4qbzb51li",
+    "version": "1.1.0"
+  },
+  "wp-user-avatars": {
+    "path": "wp-user-avatars/trunk",
+    "rev": "2540784",
+    "sha256": "1g21nl6xs9zyq0ainjwa06wl90975l8f9rj0fa20zkmw17w2mdgl",
+    "version": "1.4.1"
+  },
+  "wpforms-lite": {
+    "path": "wpforms-lite/tags/1.8.5.3",
+    "rev": "3009465",
+    "sha256": "1xj4wn1zfdjqxh1h6k9xa316276k8n26nmgjfcapwss452qajwkm",
+    "version": "1.8.5.3"
+  }
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/packages/themes.json b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/themes.json
new file mode 100644
index 000000000000..92d09ef4ca97
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/themes.json
@@ -0,0 +1,32 @@
+{
+  "twentynineteen": {
+    "path": "twentynineteen/2.7",
+    "rev": "207575",
+    "sha256": "19zbbpj1qxfz6599di2455qr97z5x4vrprf0bf20c8dq8n8lrh41",
+    "version": "2.7"
+  },
+  "twentytwenty": {
+    "path": "twentytwenty/2.4",
+    "rev": "207576",
+    "sha256": "0xp2jcgsn16gv9ad8dirm7j24mi7633yrl524wi858l3m8dh4q4a",
+    "version": "2.4"
+  },
+  "twentytwentyone": {
+    "path": "twentytwentyone/2.0",
+    "rev": "207577",
+    "sha256": "0ypdqxfd1va9m6f3zbc0281i69br5hpvvjdqb03kk2xnmam2hjaa",
+    "version": "2.0"
+  },
+  "twentytwentythree": {
+    "path": "twentytwentythree/1.3",
+    "rev": "207579",
+    "sha256": "0r2k73yskqaxhl641ri1shy74rck5xvmfi7b562kz3j44hx0dz4f",
+    "version": "1.3"
+  },
+  "twentytwentytwo": {
+    "path": "twentytwentytwo/1.6",
+    "rev": "207578",
+    "sha256": "0ga1682a5sh038xfc7whvdws5vfy1g3qvvy13rm5dln79x022riq",
+    "version": "1.6"
+  }
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/packages/thirdparty.nix b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/thirdparty.nix
new file mode 100644
index 000000000000..24836f3ac42c
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/thirdparty.nix
@@ -0,0 +1,25 @@
+{fetchzip, stdenv, lib}: {
+  plugins.civicrm = stdenv.mkDerivation rec {
+    pname = "civicrm";
+    version = "5.56.0";
+    src = fetchzip {
+      inherit version;
+      name = pname;
+      url = "https://storage.googleapis.com/${pname}/${pname}-stable/${version}/${pname}-${version}-wordpress.zip";
+      hash = "sha256-XsNFxVL0LF+OHlsqjjTV41x9ERLwMDq9BnKKP3Px2aI=";
+    };
+    meta.license = lib.licenses.agpl3Only;
+  };
+  themes.geist = stdenv.mkDerivation rec {
+    pname = "geist";
+    version = "2.0.3";
+    src = fetchzip {
+      inherit version;
+      name = pname;
+      url = "https://github.com/christophery/geist/archive/refs/tags/${version}.zip";
+      hash = "sha256-c85oRhqu5E5IJlpgqKJRQITur1W7x40obOvHZbPevzU=";
+    };
+    meta.license = lib.licenses.gpl2Only;
+  };
+}
+
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-languages.json b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-languages.json
new file mode 100644
index 000000000000..2c6fa9785c8b
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-languages.json
@@ -0,0 +1,5 @@
+{
+  "de_DE": "gpl2Plus"
+, "fr_FR": "gpl2Plus"
+, "ro_RO": "gpl2Plus"
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-plugins.json b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-plugins.json
new file mode 100644
index 000000000000..f8e8074ab82c
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-plugins.json
@@ -0,0 +1,38 @@
+{
+  "add-widget-after-content": "gpl3Plus"
+, "akismet": "gpl2Plus"
+, "antispam-bee": "gpl2Plus"
+, "async-javascript": "gpl2Plus"
+, "breeze": "gpl2Plus"
+, "code-syntax-block": "gpl2Plus"
+, "cookie-notice": "mit"
+, "co-authors-plus": "gpl2Plus"
+, "disable-xml-rpc": "gpl2Plus"
+, "embed-extended": "gpl2Plus"
+, "gutenberg": "gpl2Plus"
+, "hello-dolly": "gpl2Plus"
+, "hkdev-maintenance-mode": "gpl2Plus"
+, "jetpack": "gpl2Plus"
+, "jetpack-lite": "gpl2Only"
+, "lightbox-photoswipe": "gpl2Only"
+, "login-lockdown": "gpl2Plus"
+, "mailpoet": "gpl3Only"
+, "merge-minify-refresh": "gpl2Plus"
+, "opengraph": "asl20"
+, "simple-login-captcha": "gpl2Plus"
+, "simple-mastodon-verification": "gpl2Plus"
+, "static-mail-sender-configurator": "mit"
+, "tc-custom-javascript": "gpl2Plus"
+, "webp-converter-for-media": "gpl2Plus"
+, "webp-express": "gpl3Only"
+, "wordpress-seo": "gpl3Only"
+, "worker": "gpl3Plus"
+, "wp-change-email-sender": "gpl2Plus"
+, "wp-fastest-cache": "gpl2Plus"
+, "wp-gdpr-compliance": "gpl2Plus"
+, "wp-mail-smtp": "gpl3Plus"
+, "wp-statistics": "gpl3Only"
+, "wp-swiper": "gpl2Plus"
+, "wp-user-avatars": "gpl2Plus"
+, "wpforms-lite": "gpl2Plus"
+}
diff --git a/nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-themes.json b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-themes.json
new file mode 100644
index 000000000000..b41c2f18f816
--- /dev/null
+++ b/nixpkgs/pkgs/servers/web-apps/wordpress/packages/wordpress-themes.json
@@ -0,0 +1,7 @@
+{
+  "twentynineteen": "gpl2Plus"
+, "twentytwenty": "gpl2Plus"
+, "twentytwentytwo": "gpl2Plus"
+, "twentytwentyone": "gpl2Plus"
+, "twentytwentythree": "gpl2Plus"
+}