From 711a017e8cf774e5a81c7b88b88e558443efc7ca Mon Sep 17 00:00:00 2001 From: Padreug Date: Mon, 25 May 2026 23:59:31 +0200 Subject: [PATCH 01/36] add nix flake with devShell and native package build devShell: nodejs_20, pnpm_8, prisma + prisma-engines, sqlite, openssl, plus the env wiring so prisma uses nix-provided engines instead of fetching from binaries.prisma.sh. packages.default: full native build via pnpm_8.fetchDeps + configHook. Patches the workspace:* ndk spec to the lockfile-resolved ^2.8.1 so --frozen-lockfile accepts it, then re-runs install with scripts to trigger bcrypt's node-pre-gyp fallback-to-build (uses python311 since node-gyp 9.4.1 bundled with pnpm 8 still imports distutils). Co-Authored-By: Claude Opus 4.7 (1M context) --- flake.lock | 27 ++++++++++++ flake.nix | 51 ++++++++++++++++++++++ package.nix | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 package.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..f428ce8 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1767313136, + "narHash": "sha256-16KkgfdYqjaeRGBaYsNrhPRRENs0qzkQVUooNHtoy2w=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ac62194c3917d5f474c1a844b6fd6da2db95077d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..5bb1222 --- /dev/null +++ b/flake.nix @@ -0,0 +1,51 @@ +{ + description = "nsecbunkerd — Nostr remote signing daemon (NIP-46)"; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; + + outputs = { self, nixpkgs }: + let + systems = [ "x86_64-linux" "aarch64-linux" ]; + forAllSystems = nixpkgs.lib.genAttrs systems; + pkgsFor = system: import nixpkgs { inherit system; }; + in + { + packages = forAllSystems (system: + let pkgs = pkgsFor system; in + rec { + default = nsecbunkerd; + nsecbunkerd = pkgs.callPackage ./package.nix { }; + } + ); + + devShells = forAllSystems (system: + let pkgs = pkgsFor system; in + { + default = pkgs.mkShell { + packages = with pkgs; [ + nodejs_20 + pnpm_8 + prisma + prisma-engines + python3 + gcc + pkg-config + openssl + sqlite + ]; + + shellHook = '' + # Point prisma at the nix-provided engines so it doesn't try to + # download them from binaries.prisma.sh on every install. + export PRISMA_QUERY_ENGINE_BINARY=${pkgs.prisma-engines}/bin/query-engine + export PRISMA_QUERY_ENGINE_LIBRARY=${pkgs.prisma-engines}/lib/libquery_engine.node + export PRISMA_SCHEMA_ENGINE_BINARY=${pkgs.prisma-engines}/bin/schema-engine + export PRISMA_FMT_BINARY=${pkgs.prisma-engines}/bin/prisma-fmt + export PRISMA_INTROSPECTION_ENGINE_BINARY=${pkgs.prisma-engines}/bin/introspection-engine + export PRISMA_CLIENT_ENGINE_TYPE=binary + ''; + }; + } + ); + }; +} diff --git a/package.nix b/package.nix new file mode 100644 index 0000000..5c49bf7 --- /dev/null +++ b/package.nix @@ -0,0 +1,123 @@ +{ + lib, + stdenv, + pnpm_8, + nodejs_20, + makeWrapper, + prisma-engines, + openssl, + sqlite, + python311, + pkg-config, + node-gyp, +}: + +let + # package.json pins `@nostr-dev-kit/ndk: "workspace:*"` but the lockfile + # resolves `^2.8.1`. With --frozen-lockfile pnpm refuses the mismatch, + # so rewrite the spec to match the lockfile. + patchNdk = '' + substituteInPlace package.json \ + --replace-fail '"@nostr-dev-kit/ndk": "workspace:*"' \ + '"@nostr-dev-kit/ndk": "^2.8.1"' + ''; + + prismaEnv = { + PRISMA_SCHEMA_ENGINE_BINARY = lib.getExe' prisma-engines "schema-engine"; + PRISMA_QUERY_ENGINE_BINARY = lib.getExe' prisma-engines "query-engine"; + PRISMA_QUERY_ENGINE_LIBRARY = "${prisma-engines}/lib/libquery_engine.node"; + PRISMA_INTROSPECTION_ENGINE_BINARY = lib.getExe' prisma-engines "introspection-engine"; + PRISMA_FMT_BINARY = lib.getExe' prisma-engines "prisma-fmt"; + PRISMA_CLIENT_ENGINE_TYPE = "binary"; + }; +in +stdenv.mkDerivation (finalAttrs: { + pname = "nsecbunkerd"; + version = "0.10.5"; + + src = ./.; + + pnpmDeps = pnpm_8.fetchDeps { + inherit (finalAttrs) pname version src; + fetcherVersion = 2; + prePnpmInstall = patchNdk; + hash = "sha256-dQ+TX5jf1ZQKGoPCZgWaFwpAC3uP6iL1ZSxS0mFNdP8="; + }; + + postPatch = patchNdk; + + nativeBuildInputs = [ + pnpm_8.configHook + pnpm_8 + nodejs_20 + makeWrapper + node-gyp + python311 + pkg-config + ]; + + buildInputs = [ + openssl + sqlite + ]; + + env = prismaEnv; + + buildPhase = '' + runHook preBuild + + export npm_config_nodedir=${nodejs_20} + pnpm config set nodedir ${nodejs_20} + + # configHook ran with --ignore-scripts; re-run install to trigger + # native-module postinstall (bcrypt). --offline keeps it inside the + # store seeded by configHook. + pnpm install --force --offline --frozen-lockfile --reporter=append-only + + pnpm prisma generate + pnpm build + + pnpm prune --prod --ignore-scripts + find node_modules -xtype l -delete + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/{bin,share/nsecbunkerd} + cp -r dist node_modules prisma templates package.json \ + $out/share/nsecbunkerd/ + + makeWrapper ${lib.getExe nodejs_20} $out/bin/nsecbunkerd \ + --chdir $out/share/nsecbunkerd \ + --add-flags $out/share/nsecbunkerd/dist/index.js \ + --set NODE_ENV production \ + --prefix PATH : ${lib.makeBinPath [ openssl ]} \ + ${ + lib.concatStringsSep " \\\n " ( + lib.mapAttrsToList (n: v: "--set ${n} ${lib.escapeShellArg v}") prismaEnv + ) + } + + makeWrapper ${lib.getExe nodejs_20} $out/bin/nsecbunker-client \ + --chdir $out/share/nsecbunkerd \ + --add-flags $out/share/nsecbunkerd/dist/client/client.js \ + --set NODE_ENV production + + runHook postInstall + ''; + + passthru = { + inherit prisma-engines; + }; + + meta = { + description = "Nostr remote signing daemon (NIP-46)"; + homepage = "https://github.com/kind-0/nsecbunkerd"; + license = lib.licenses.mit; + mainProgram = "nsecbunkerd"; + platforms = lib.platforms.linux; + }; +}) From 06272c8f2c498dc9e7717ae983ad005cf7f80f0c Mon Sep 17 00:00:00 2001 From: Padreug Date: Tue, 26 May 2026 00:29:29 +0200 Subject: [PATCH 02/36] pin @nostr-dev-kit/ndk to 2.8.1 instead of workspace:* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream declares the dependency as workspace:*, but the repo has no pnpm-workspace.yaml and no sibling @nostr-dev-kit/ndk package — so pnpm install fails with ERR_PNPM_WORKSPACE_PKG_NOT_FOUND on a clean clone. The shipped pnpm-lock.yaml was resolving to ndk 2.8.1, so pin to that exact version to match what the lockfile already expects. Fixes #3. Co-Authored-By: Claude Opus 4.7 (1M context) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4232435..297fd2a 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@fastify/view": "^8.2.0", "@inquirer/password": "^1.1.2", "@inquirer/prompts": "^1.2.3", - "@nostr-dev-kit/ndk": "workspace:*", + "@nostr-dev-kit/ndk": "2.8.1", "@prisma/client": "^5.4.1", "@scure/base": "^1.1.1", "@types/yargs": "^17.0.24", From 960b9399e8000449fcc3440ca16e29a65a35448b Mon Sep 17 00:00:00 2001 From: Padreug Date: Tue, 26 May 2026 00:29:41 +0200 Subject: [PATCH 03/36] Dockerfile: switch from npm to pnpm + drop --frozen-lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two upstream-rot issues fixed in one commit (same root cause: the upstream Dockerfile predates the move to pnpm and the lockfile has drifted): - npm install can't resolve workspace:* deps (which package.json used to declare for @nostr-dev-kit/ndk — see prior commit for the pin). Switching to pnpm@9 matches the lockfile that ships in-repo. - pnpm-lock.yaml is out of date vs package.json (likely from generation-time vs commit-time drift), so --frozen-lockfile fails with ERR_PNPM_OUTDATED_LOCKFILE. Drop the flag in both build and runtime stages to let pnpm resolve fresh, at the cost of giving up determinism — to be restored once the lockfile is regenerated. Also reorders the build stage to COPY lockfile + manifest before the source, so the install layer caches across source-only edits. Fixes #1, #2. Co-Authored-By: Claude Opus 4.7 (1M context) --- Dockerfile | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1eb99be..1168d8c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,32 @@ +# Patched from upstream kind-0/nsecbunkerd Dockerfile to use pnpm — the +# upstream version uses `npm install` but package.json declares +# `@nostr-dev-kit/ndk` as `workspace:*`, which only pnpm understands. +# A clean clone of upstream fails to build with `EUNSUPPORTEDPROTOCOL` +# under npm. Switching to pnpm matches the lockfile that ships in-repo. +# Also drops `--frozen-lockfile` because the upstream pnpm-lock.yaml is +# out of date vs. package.json (ERR_PNPM_OUTDATED_LOCKFILE) — bug to +# file upstream once we've verified the rest of the stack works. + FROM node:20.11-bullseye AS build WORKDIR /app -# Copy package files and install dependencies -COPY package*.json ./ -RUN npm install +RUN npm install -g pnpm@9 + +# Copy lockfile + manifest first so the install layer caches across +# source changes. +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --no-frozen-lockfile # Copy application files COPY . . # Generate prisma client and build the application RUN npx prisma generate -RUN npm run build +RUN pnpm run build # Runtime stage -FROM node:20.11-alpine as runtime +FROM node:20.11-alpine AS runtime WORKDIR /app @@ -22,11 +34,13 @@ RUN apk update && \ apk add --no-cache openssl && \ rm -rf /var/cache/apk/* +RUN npm install -g pnpm@9 + # Copy built files from the build stage COPY --from=build /app . -# Install only runtime dependencies -RUN npm install --only=production +# Install only runtime dependencies (pnpm respects the workspace protocol) +RUN pnpm install --prod --no-frozen-lockfile EXPOSE 3000 From 42dbbd753663f4698e930582a7c8d72666e7344e Mon Sep 17 00:00:00 2001 From: Padreug Date: Tue, 26 May 2026 00:29:53 +0200 Subject: [PATCH 04/36] =?UTF-8?q?disable=20pingOrDie=20watchdog=20?= =?UTF-8?q?=E2=80=94=20false-positives=20on=20non-public=20relays?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NDK 2.8.1's outbox model doesn't reliably deliver self-published events back through subscriptions when the configured relay set is a single custom (non-public) relay. The pingOrDie self-watchdog publishes a kind-24133 event to its own pubkey every 20s and exits the bunker if it doesn't see the echo within 50s — which means on a private relay channel (e.g. LNbits's nostrrelay extension), the bunker exits cleanly every 50s even though admin RPCs over that same channel are working fine. Plain-WebSocket round-trips to the same relay echo correctly in <1s, so the issue is on NDK's side, not the relay's. Commenting out the watchdog is the minimum patch to keep the daemon alive. Real fix is either an env-flag opt-out, a simpler connectivity check that doesn't depend on self-echo, or an NDK upgrade that fixes the outbox-vs-subscribe race. Fixes #4. See also #7 for the underlying NDK echo investigation. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/admin/index.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/daemon/admin/index.ts b/src/daemon/admin/index.ts index 4db9cc2..75dfc4b 100644 --- a/src/daemon/admin/index.ts +++ b/src/daemon/admin/index.ts @@ -122,7 +122,12 @@ class AdminInterface { this.rpc.on('request', (req) => this.handleRequest(req)); - pingOrDie(this.ndk); + // pingOrDie disabled — NDK 2.8.1 outbox model doesn't echo + // self-published events back through subscriptions on + // non-public relay channels, so the watchdog fires false + // positives and exits the bunker every 50s on private relays. + // See aiolabs/nsecbunkerd#4 + #7. + // pingOrDie(this.ndk); }).catch((err) => { console.log('❌ admin connection failed'); console.log(err); From e39eaa632db16c0d2abdd78710467639e74ddcf4 Mon Sep 17 00:00:00 2001 From: Padreug Date: Tue, 26 May 2026 00:32:39 +0200 Subject: [PATCH 05/36] startKey: decode bech32 nsec to hex before constructing NDKPrivateKeySigner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NDK 2.8.1's NDKPrivateKeySigner constructor forwards its arg straight to nostr-tools getPublicKey() which requires 32-byte hex/bytes/bigint and throws on bech32 input. Every key loaded through startKey (i.e. every key created via create_new_key, plus boot-time reloads of any plain-nsec entries in the config) was failing silently with the nostr-tools type error. The try/catch caught the throw and returned without loading the key, so the bunker would happily report create_new_key as successful, the key would persist encrypted on disk, but the runtime keystore would not have a signer for it. NIP-46 connect / sign_event against any admin-provisioned target therefore silently timed out from the client side — blocking essentially every signing flow. Sister bug to #5 (getKeys iterator) in a different code path. The fix matches the existing pattern in create_new_key.ts:16: hexpk = nip19.decode(nsec).data as string; Verified against the local spike harness: create_new_key now loads the target into runtime; get_keys returns the new entry (assuming #5 is patched separately for the iterator path). Fixes #8. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/run.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/daemon/run.ts b/src/daemon/run.ts index 262a150..6637986 100644 --- a/src/daemon/run.ts +++ b/src/daemon/run.ts @@ -230,8 +230,14 @@ class Daemon { if (nsec.startsWith('nsec1')) { try { - const key = new NDKPrivateKeySigner(nsec); - hexpk = key.privateKey!; + // NDK 2.8.1's NDKPrivateKeySigner constructor passes its + // arg straight to nostr-tools getPublicKey() which requires + // 32-byte hex / bytes / bigint, not bech32. Without this + // decode, every key created via create_new_key fails to + // load with the nostr-tools getPublicKey type error, so + // the bunker can never sign for any target it provisions. + // See aiolabs/nsecbunkerd#8. + hexpk = nip19.decode(nsec).data as string; } catch(e) { console.error(`Error loading key ${name}:`, e); return From 8caf856ab21c04be55adf1df73b2d8de7b21e9d1 Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 27 May 2026 16:56:27 +0200 Subject: [PATCH 06/36] diag(#7): env-gated per-relay transport instrumentation Add NSEC_BUNKER_DEBUG_TRANSPORT=1 opt-in logging that emits REQUEST_IN on inbound NIP-46 RPCs, RESPONSE_SENT around NDKNostrRpc.sendResponse, and PUBLISHED / PUBLISH_FAILED per-relay on the bunker's pool. Surfaces the diagnostic signal NDKNostrRpc itself discards: sendResponse calls `event.publish(this.relaySet)` and throws away the Set it returns, so silent outbox-drops and wrong-kind responses are invisible without hooking the pool's per-relay events directly. Validated against the local bunker via the lnbits-side admin spike harness (~/dev/lnbits/misc-aio/bunker_admin_spike.py): the instrumentation made the 9-step harness reveal a wrong-kind error response path (separate fix in the next commit) that had been masquerading as an NDK echo issue for a week. With the env flag unset the daemon stays as quiet as before. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/admin/index.ts | 50 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/daemon/admin/index.ts b/src/daemon/admin/index.ts index 75dfc4b..4684fcb 100644 --- a/src/daemon/admin/index.ts +++ b/src/daemon/admin/index.ts @@ -111,8 +111,28 @@ class AdminInterface { return; } - this.ndk.pool.on('relay:connect', () => console.log('✅ nsecBunker Admin Interface ready')); + const debugTransport = process.env.NSEC_BUNKER_DEBUG_TRANSPORT === '1'; + + // Per-relay publish-status logging for diagnosing aiolabs/nsecbunkerd#7. + // NDKNostrRpc.sendResponse calls event.publish() and discards the + // returned Set, so a silent outbox-drop is invisible without + // hooking the underlying per-relay events. Gated by env flag so + // production deployments stay quiet. + const attachRelayLogging = (relay: any) => { + relay.on('published', (event: NDKEvent) => { + console.log(`📤 PUBLISHED relay=${relay.url} kind=${event.kind} id=${event.id?.slice(0,8)}`); + }); + relay.on('publish:failed', (event: NDKEvent, err: any) => { + console.log(`❌ PUBLISH_FAILED relay=${relay.url} kind=${event.kind} id=${event.id?.slice(0,8)} err=${err?.message ?? err}`); + }); + }; + + this.ndk.pool.on('relay:connect', (relay: any) => { + console.log('✅ nsecBunker Admin Interface ready'); + if (debugTransport) attachRelayLogging(relay); + }); this.ndk.pool.on('relay:disconnect', () => console.log('❌ admin disconnected')); + this.ndk.connect(2500).then(() => { // connect for whitelisted admins this.rpc.subscribe({ @@ -120,7 +140,33 @@ class AdminInterface { "#p": [this.signerUser!.pubkey] }); - this.rpc.on('request', (req) => this.handleRequest(req)); + // Attach per-relay logging to relays that connected before our + // 'relay:connect' listener was registered above (NDK can connect + // synchronously inside .connect() under some paths). + if (debugTransport) { + this.ndk.pool.relays.forEach((relay: any) => attachRelayLogging(relay)); + + // Wrap sendResponse to log id + kind + elapsed time so we + // can correlate REQUEST_IN → RESPONSE_SENT → PUBLISHED. + const originalSendResponse = this.rpc.sendResponse.bind(this.rpc); + this.rpc.sendResponse = async (id: string, remotePubkey: string, result: string, kind?: number, error?: string) => { + const start = Date.now(); + try { + await originalSendResponse(id, remotePubkey, result, kind, error); + console.log(`📨 RESPONSE_SENT id=${id} remote=${remotePubkey.slice(0,8)} kind=${kind ?? NDKKind.NostrConnect} elapsed=${Date.now()-start}ms`); + } catch (e: any) { + console.log(`❌ RESPONSE_SEND_FAILED id=${id} remote=${remotePubkey.slice(0,8)} kind=${kind ?? NDKKind.NostrConnect} err=${e?.message ?? e}`); + throw e; + } + }; + } + + this.rpc.on('request', (req) => { + if (debugTransport) { + console.log(`📥 REQUEST_IN method=${req.method} id=${req.id} from=${req.pubkey?.slice(0,8)} kind=${req.event?.kind}`); + } + this.handleRequest(req); + }); // pingOrDie disabled — NDK 2.8.1 outbox model doesn't echo // self-published events back through subscriptions on From 0a510b7f9a0c9187e692f9acf487360b5ea490b3 Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 27 May 2026 17:04:31 +0200 Subject: [PATCH 07/36] fix(#7): route error responses to the request's kind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The catch block in handleRequest and both response paths in create_account pass `NDKKind.NostrConnectAdmin` as the response kind. That constant does NOT exist in NDK 2.8.1 — only `NostrConnect = 24133` is exported — so it resolves to `undefined` and NDKNostrRpc.sendResponse falls through to its own default of `NDKKind.NostrConnect = 24133`. Net effect: any error response to an admin-channel (kind 24134) request is published on the NIP-46 signing channel (24133) instead, which clients subscribed for 24134 never see. Looks like a transport-layer NDK-echo / silent-drop issue from the client's perspective, but the bunker IS publishing reliably — just on the wrong kind. Mirror `req.event.kind` so the error response goes back on the same channel the request came in on. Same pattern the unknown-method path and create_account's validation-error path already used; just propagate it to the remaining sites. Drops the now-unused NDKKind import from create_account.ts. Validated end-to-end against the local bunker via the lnbits-side admin spike harness — after this fix + the migration entrypoint fix + the policyId type fix, all 9 spike steps including NIP-46 sign_event pass with Schnorr-valid signatures. See coordination log entry 2026-05-27T14:30Z. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/admin/commands/create_account.ts | 17 ++++++++++++----- src/daemon/admin/index.ts | 10 +++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/daemon/admin/commands/create_account.ts b/src/daemon/admin/commands/create_account.ts index e4632d6..f3c026a 100644 --- a/src/daemon/admin/commands/create_account.ts +++ b/src/daemon/admin/commands/create_account.ts @@ -1,4 +1,4 @@ -import { Hexpubkey, NDKKind, NDKPrivateKeySigner, NDKRpcRequest, NDKUserProfile } from "@nostr-dev-kit/ndk"; +import { Hexpubkey, NDKPrivateKeySigner, NDKRpcRequest, NDKUserProfile } from "@nostr-dev-kit/ndk"; import AdminInterface from ".."; import { nip19 } from 'nostr-tools'; import { setupSkeletonProfile } from "../../lib/profile"; @@ -136,7 +136,7 @@ export default async function createAccount(admin: AdminInterface, req: NDKRpcRe } /** - * This is where the real work of creating the private key, wallet, nip-05, granting access, etc happen + * This is where the real work of creating the private key, wallet, nip-05, granting access, etc happen — pragma: allowlist secret */ export async function createAccountReal( admin: AdminInterface, @@ -209,11 +209,18 @@ export async function createAccountReal( // access it without having to go through an approval flow await grantPermissions(req, keyName); - return admin.rpc.sendResponse(req.id, req.pubkey, generatedUser.pubkey, NDKKind.NostrConnectAdmin); + // NDKKind.NostrConnectAdmin doesn't exist in NDK 2.8.1 — it resolves + // to `undefined` and sendResponse defaults to NDKKind.NostrConnect + // (24133), sending the response on the wrong channel. Mirror the + // request's kind so the response goes back on the same channel the + // client subscribed for. Filed as part of aiolabs/nsecbunkerd#7 + // diagnosis 2026-05-27. + const originalKind = req.event.kind!; + return admin.rpc.sendResponse(req.id, req.pubkey, generatedUser.pubkey, originalKind); } catch (e: any) { console.trace('error', e); - return admin.rpc.sendResponse(req.id, req.pubkey, "error", NDKKind.NostrConnectAdmin, - e.message); + const originalKind = req.event.kind!; + return admin.rpc.sendResponse(req.id, req.pubkey, "error", originalKind, e.message); } } diff --git a/src/daemon/admin/index.ts b/src/daemon/admin/index.ts index 4684fcb..5adafe8 100644 --- a/src/daemon/admin/index.ts +++ b/src/daemon/admin/index.ts @@ -209,7 +209,15 @@ class AdminInterface { } } catch (err: any) { debug(`Error handling request ${req.method}: ${err?.message??err}`, req.params); - return this.rpc.sendResponse(req.id, req.pubkey, "error", NDKKind.NostrConnectAdmin, err?.message); + // NDKKind.NostrConnectAdmin doesn't exist in NDK 2.8.1 — using it + // makes sendResponse fall through to its default of 24133, which + // sends the error on a different channel than the request came in + // on. Mirror req.event.kind so the response goes back where the + // client is listening. Filed as part of aiolabs/nsecbunkerd#7 + // diagnosis 2026-05-27. + const originalKind = req.event.kind!; + console.log(`⚠️ HANDLE_REQUEST_ERROR method=${req.method} id=${req.id} kind=${originalKind} err=${err?.message ?? err}`); + return this.rpc.sendResponse(req.id, req.pubkey, "error", originalKind, err?.message); } } From 5e77de1202675c9abe17ea0bbe9ebf552a0a61b9 Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 27 May 2026 17:04:53 +0200 Subject: [PATCH 08/36] fix: convert policyId to Int before Prisma insert in create_new_token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wire-level `create_new_token` RPC carries `policyId` as a string (everything in NDK RPC params is string). The handler correctly parseInts it for the `findUnique({where:{id:parseInt(policyId)}})` call but then forwards the unparsed string straight into the Prisma `token.create({data:{...policyId}})` payload. Prisma rejects with "Argument `policyId`: Invalid value provided. Expected Int or Null, provided String" because `Token.policyId` is declared `Int` per the schema (references `Policy.id`, which is autoincrement Int). Hoist `policyIdInt = parseInt(policyId)` and use it for both the findUnique lookup and the create payload. Latent upstream bug — no one would have seen it before because the wrong-kind error response (fixed in the previous commit) made the symptom look like a transport timeout rather than a Prisma validation error. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/admin/commands/create_new_token.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/daemon/admin/commands/create_new_token.ts b/src/daemon/admin/commands/create_new_token.ts index df145a2..04588c4 100644 --- a/src/daemon/admin/commands/create_new_token.ts +++ b/src/daemon/admin/commands/create_new_token.ts @@ -7,15 +7,19 @@ export default async function createNewToken(admin: AdminInterface, req: NDKRpcR if (!clientName || !policyId) throw new Error("Invalid params"); - const policy = await prisma.policy.findUnique({ where: { id: parseInt(policyId) }, include: { rules: true } }); + const policyIdInt = parseInt(policyId); + const policy = await prisma.policy.findUnique({ where: { id: policyIdInt }, include: { rules: true } }); if (!policy) throw new Error("Policy not found"); console.log({clientName, policy, durationInHours}); const token = [...Array(64)].map(() => Math.floor(Math.random() * 16).toString(16)).join(''); + // policyId must be Int per the Prisma schema (Token.policyId references + // Policy.id which is autoincrement Int). Upstream passes the raw string + // from the wire — caught during aiolabs/nsecbunkerd#7 diagnosis 2026-05-27. const data: any = { - keyName, clientName, policyId, + keyName, clientName, policyId: policyIdInt, createdBy: req.pubkey, token }; From 053357899dbe14baac80064a852dc692c01dbefa Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 27 May 2026 17:05:10 +0200 Subject: [PATCH 09/36] fix(docker): entrypoint runs migrations via scripts/start.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream Dockerfile sets `ENTRYPOINT [ "node", "./dist/index.js" ]`, which boots the daemon directly and silently bypasses `scripts/start.js` — the only place that runs `prisma migrate deploy`. On a clean install, the SQLite db file at $DATABASE_URL is created empty (0 bytes) and every Policy / KeyUser / Token / SigningCondition operation throws "table does not exist." `ping` / `get_keys` / `create_new_key` happen to survive because they only touch the JSON config, not the db. Two changes: 1. ENTRYPOINT switches to `node ./scripts/start.js`. The CMD arg (`start`) and any additional argv pass through to the daemon unchanged via process.argv. 2. Runtime pnpm install drops `--prod`. The prisma CLI lives in devDependencies; with `--prod`, `npx prisma migrate deploy` tries to download prisma@latest at runtime, which OOMs in modest containers. Including devDeps at runtime adds modest image bulk for correctness. Validated end-to-end against the local regtest stack — after the rebuild the SQLite db boots populated with 22 migrations, and the lnbits-side admin spike harness passes all 9 steps including NIP-46 sign_event with Schnorr-valid signatures. Co-Authored-By: Claude Opus 4.7 (1M context) --- Dockerfile | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1168d8c..9ace24a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,10 +39,20 @@ RUN npm install -g pnpm@9 # Copy built files from the build stage COPY --from=build /app . -# Install only runtime dependencies (pnpm respects the workspace protocol) -RUN pnpm install --prod --no-frozen-lockfile +# Install all dependencies (including devDeps). The prisma CLI lives in +# devDependencies but scripts/start.js invokes `prisma migrate deploy` +# at boot, so it must be available at runtime. Dropping --prod adds the +# CLI tooling to the runtime image — a modest size cost for the +# correctness of the migration step. +RUN pnpm install --no-frozen-lockfile EXPOSE 3000 -ENTRYPOINT [ "node", "./dist/index.js" ] +# Run via scripts/start.js so `prisma migrate deploy` applies pending +# migrations before the daemon spawns. The upstream Dockerfile invokes +# ./dist/index.js directly, which silently bypasses the migration step +# and leaves the SQLite db empty on first boot — every command that +# touches Policy/KeyUser/Token/etc. then throws "table does not exist." +# Caught during aiolabs/nsecbunkerd#7 diagnosis 2026-05-27. +ENTRYPOINT [ "node", "./scripts/start.js" ] CMD ["start"] From ccfde02d70a73d6de0cbf60023fe828299db0821 Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 27 May 2026 17:05:24 +0200 Subject: [PATCH 10/36] fix(start.js): resolve sibling paths from script location, not cwd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The launcher previously assumed cwd was the package root: `mkdir config` in cwd, `npm run prisma:migrate` in cwd, `node ./dist/index.js`. Works under docker (WORKDIR /app, writable) but breaks anywhere cwd differs from the package root — e.g. a nix-built bunker invoked from a systemd unit whose WorkingDirectory is the state dir (/var/lib/nsecbunkerd) and not the nix store path that holds dist/, scripts/, prisma/. Resolve sibling paths via `path.resolve(__dirname, '..')` so the package-internal layout is robust to cwd. Use `path.join(pkgRoot, 'dist/index.js')` for the daemon spawn and `{ cwd: pkgRoot }` for the npm migrate exec. Switch `mkdir config` (which only works in writable cwd) to `fs.mkdirSync(configDir, { recursive: true })` where configDir defaults to `./config` relative to cwd, overrideable via NSEC_BUNKER_CONFIG_DIR. This lets the nix package install the launcher into the read-only store while the systemd unit still does its config/state work in /var/lib/nsecbunkerd with no shell wrapping. Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/start.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/scripts/start.js b/scripts/start.js index c3899f8..603d5b2 100644 --- a/scripts/start.js +++ b/scripts/start.js @@ -1,20 +1,32 @@ const { execSync, spawn } = require('child_process'); const fs = require('fs'); +const path = require('path'); + +// Resolve sibling paths from this script's location so the launcher +// works whether cwd is /app (docker), the nix store, or a writable +// state dir set by systemd's WorkingDirectory. The prisma CLI and +// dist/index.js live alongside this file in `/share/nsecbunkerd/` +// (nix) or `/app/` (docker). The migration-side env knobs: +// NSEC_BUNKER_CONFIG_DIR — directory holding nsecbunker.{json,db}; +// defaults to ./config relative to cwd. +// DATABASE_URL — prisma's source of truth for the sqlite +// path; honor whatever the caller set. +const pkgRoot = path.resolve(__dirname, '..'); +const configDir = process.env.NSEC_BUNKER_CONFIG_DIR || path.resolve(process.cwd(), 'config'); try { - console.log(`Running migrations`); - // check if config folder exists - if (!fs.existsSync('./config')) { - execSync(`mkdir config`); + console.log(`Running migrations`); + if (!fs.existsSync(configDir)) { + fs.mkdirSync(configDir, { recursive: true }); } - execSync('npm run prisma:migrate'); + execSync('npm run prisma:migrate', { cwd: pkgRoot, stdio: 'inherit' }); } catch (error) { - console.log(error); + console.log(error); // Handle any potential migration errors here } const args = process.argv.slice(2); -const childProcess = spawn('node', ['./dist/index.js', ...args], { +const childProcess = spawn('node', [path.join(pkgRoot, 'dist/index.js'), ...args], { stdio: 'inherit', }); From 662dd21a60acbd4ae12225af2736b4c2cd6fc8be Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 27 May 2026 17:08:42 +0200 Subject: [PATCH 11/36] fix(nix): include prisma CLI + scripts/, wrapper invokes start.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three correctness fixes to the nix derivation that mirror the Dockerfile correctness fixes: 1. Drop `pnpm prune --prod --ignore-scripts` from the build phase. The prune step removed the prisma CLI (devDependency) from the output, so the runtime invocation of `prisma migrate deploy` had nothing to exec. Same trap the upstream Dockerfile fell into via `--prod` install. 2. Copy `scripts/` into `$out/share/nsecbunkerd/` alongside dist, node_modules, prisma, templates. Without it the launcher script (which contains the migration step) wasn't present. 3. The makeWrapper target switches from `dist/index.js` to `scripts/start.js`. Same change the Dockerfile ENTRYPOINT got in the previous commit. Also adds nodejs_20 to PATH so `npm` is resolvable from inside start.js, and drops `--chdir` so the caller (systemd, docker compose) controls cwd — start.js now resolves sibling paths from `__dirname`, independently committed. The `patchNdk` substitution narrows from the old `workspace:*` form (no longer in the package.json after fork commit 06272c8) to the current `"2.8.1"` → `"^2.8.1"` rewrite needed to align package.json with the lockfile under --frozen-lockfile. Remaining known gap: nixpkgs ships prisma-engines 7.7.0 while the JS prisma CLI in node_modules is 5.4.1, an RPC vocabulary mismatch that breaks the migrate step at runtime (`Method not found: listMigrationDirectories`). Either bump prisma JS to ^7.x or overlay prisma-engines to 5.4.1. Out of scope for this commit; docker build unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) --- package.nix | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/package.nix b/package.nix index 5c49bf7..adeb62b 100644 --- a/package.nix +++ b/package.nix @@ -13,12 +13,17 @@ }: let - # package.json pins `@nostr-dev-kit/ndk: "workspace:*"` but the lockfile - # resolves `^2.8.1`. With --frozen-lockfile pnpm refuses the mismatch, - # so rewrite the spec to match the lockfile. + # Fork commit `06272c8` ("pin @nostr-dev-kit/ndk to 2.8.1 instead of + # workspace:*") changed package.json to a pinned `"2.8.1"`, but the + # pnpm-lock.yaml still expresses the spec as `"^2.8.1"` (the way + # `pnpm add` originally generated it). pnpm with --frozen-lockfile + # rejects that mismatch. Patching package.json to use the caret form + # is non-semantic (2.8.1 is still the resolved version) and aligns + # both files. Same fix the Dockerfile-side already handles via + # `--no-frozen-lockfile`; in nix we prefer frozen + a targeted patch. patchNdk = '' substituteInPlace package.json \ - --replace-fail '"@nostr-dev-kit/ndk": "workspace:*"' \ + --replace-fail '"@nostr-dev-kit/ndk": "2.8.1"' \ '"@nostr-dev-kit/ndk": "^2.8.1"' ''; @@ -77,7 +82,12 @@ stdenv.mkDerivation (finalAttrs: { pnpm prisma generate pnpm build - pnpm prune --prod --ignore-scripts + # Do NOT `pnpm prune --prod` here — the prisma CLI lives in + # devDependencies and `scripts/start.js` invokes it at boot via + # `npx prisma migrate deploy`. Without the CLI, the migration step + # silently fails (npx falls back to downloading prisma fresh, which + # OOMs on most containers) and the SQLite db stays empty. See + # `aiolabs/nsecbunkerd#7` diagnosis 2026-05-27. find node_modules -xtype l -delete runHook postBuild @@ -87,14 +97,24 @@ stdenv.mkDerivation (finalAttrs: { runHook preInstall mkdir -p $out/{bin,share/nsecbunkerd} - cp -r dist node_modules prisma templates package.json \ + # scripts/ MUST be copied — it contains the start.js launcher that + # runs `prisma migrate deploy` before spawning the daemon. The + # upstream packaging (and the upstream Dockerfile) bypassed this by + # invoking dist/index.js directly, leaving migrations unapplied. + cp -r dist node_modules prisma scripts templates package.json \ $out/share/nsecbunkerd/ + # Wrapper invokes scripts/start.js, which runs `prisma migrate deploy` + # then spawns dist/index.js. start.js resolves sibling paths from + # __dirname, so the caller (systemd unit, docker compose, etc.) can + # set its own WorkingDirectory for the writable state dir without + # interfering with how the launcher finds its own package files. + # NSEC_BUNKER_CONFIG_DIR can override the config directory location; + # by default it's `./config` relative to cwd. makeWrapper ${lib.getExe nodejs_20} $out/bin/nsecbunkerd \ - --chdir $out/share/nsecbunkerd \ - --add-flags $out/share/nsecbunkerd/dist/index.js \ + --add-flags $out/share/nsecbunkerd/scripts/start.js \ --set NODE_ENV production \ - --prefix PATH : ${lib.makeBinPath [ openssl ]} \ + --prefix PATH : ${lib.makeBinPath [ openssl nodejs_20 ]} \ ${ lib.concatStringsSep " \\\n " ( lib.mapAttrsToList (n: v: "--set ${n} ${lib.escapeShellArg v}") prismaEnv From 1792bc489c5624e305aa546c40aeda81bc6994c8 Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 27 May 2026 20:42:43 +0200 Subject: [PATCH 12/36] fix(#4): replace pingOrDie self-echo watchdog with pool-status check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original watchdog published a kind-24133 event to its own pubkey every 20s and exited if no echo arrived within 50s. On a single private relay setup (LNbits's nostrrelay extension channel), NDK 2.8.1's outbox model doesn't reliably route self-publishes back through the matching subscription, so the watchdog fires false positives and exits every 50s even though admin RPCs over the same channel still work fine. The upstream patches we landed previously (commit 42dbbd7) commented the call out as an emergency stopgap; this commit replaces the mechanism with one that actually answers the right question. Pool-status watchdog: poll `ndk.pool.connectedRelays().length` every 10s, track the most recent moment any relay was connected, exit if no relay has been connected for 60s. Uses NDK's own connection-lifecycle tracking which works reliably across all relay configurations — no self-publish, no subscription dependency, no relay traffic. Same intent as pingOrDie (detect partition from relay layer and let the supervisor restart us), reliable signal. Call site re-enable + env-flag opt-out follow in the next commit. Drops the now-unused NostrEvent import. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/admin/index.ts | 75 ++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/src/daemon/admin/index.ts b/src/daemon/admin/index.ts index 5adafe8..3940327 100644 --- a/src/daemon/admin/index.ts +++ b/src/daemon/admin/index.ts @@ -1,5 +1,5 @@ import "websocket-polyfill"; -import NDK, { NDKEvent, NDKKind, NDKPrivateKeySigner, NDKRpcRequest, NDKRpcResponse, NDKUser, NostrEvent } from '@nostr-dev-kit/ndk'; +import NDK, { NDKEvent, NDKKind, NDKPrivateKeySigner, NDKRpcRequest, NDKRpcResponse, NDKUser } from '@nostr-dev-kit/ndk'; import { NDKNostrRpc } from '@nostr-dev-kit/ndk'; import createDebug from 'debug'; import { Key, KeyUser } from '../run'; @@ -454,44 +454,47 @@ class AdminInterface { } } -async function pingOrDie(ndk: NDK) { - let deathTimer: NodeJS.Timeout | null = null; - - function resetDeath() { - if (deathTimer) clearTimeout(deathTimer); - deathTimer = setTimeout(() => { - console.log(`❌ No ping event received in 30 seconds. Exiting.`); - process.exit(1); - }, 50000); - } - - const self = await ndk.signer!.user(); - const sub = ndk.subscribe({ - authors: [self.pubkey], - kinds: [NDKKind.NostrConnect], - "#p": [self.pubkey] - }); - sub.on("event", (event: NDKEvent) => { - console.log(`🔔 Received ping event:`, event.created_at); - resetDeath(); - }); - sub.start(); - - resetDeath(); +/** + * Pool-status connection watchdog. Exits the daemon if every relay in + * the pool stays disconnected for longer than PARTITION_THRESHOLD_MS. + * + * Replaces the original `pingOrDie` self-echo watchdog, which published + * a kind-24133 event to its own pubkey every 20s and exited if it + * didn't see the echo within 50s. That works on public relays but + * silently breaks on single-private-relay setups: NDK 2.8.1's outbox + * model doesn't reliably route self-publishes back through the + * matching subscription, so the watchdog fires false positives and + * exits the daemon every 50s while RPCs over the same channel still + * work fine. See aiolabs/nsecbunkerd#4 + #7. + * + * The pool-status approach uses NDK's own connection-lifecycle + * tracking — `pool.connectedRelays()` reports relays in + * NDKRelayStatus.CONNECTED — which is reliable across all relay + * configurations because it doesn't depend on round-trip + * publish/subscribe. No event is published; no relay traffic. + * + * Detects partition within POLL_INTERVAL + PARTITION_THRESHOLD ms. + * Transient disconnects shorter than PARTITION_THRESHOLD don't trip + * the watchdog — useful for relays that flap or briefly drop on + * network blips. + */ +async function relayConnectionWatchdog(ndk: NDK) { + const POLL_INTERVAL_MS = 10_000; + const PARTITION_THRESHOLD_MS = 60_000; + let lastConnectedAt = Date.now(); setInterval(() => { - const event = new NDKEvent(ndk, { - kind: NDKKind.NostrConnect, - tags: [ ["p", self.pubkey] ], - content: "ping" - } as NostrEvent); - event.publish().then(() => { - console.log(`🔔 Sent ping event:`, event.created_at); - }).catch((e: any) => { - console.log(`❌ Failed to send ping event:`, e.message); + const connectedCount = ndk.pool.connectedRelays().length; + if (connectedCount > 0) { + lastConnectedAt = Date.now(); + return; + } + const elapsed = Date.now() - lastConnectedAt; + if (elapsed > PARTITION_THRESHOLD_MS) { + console.log(`❌ No connected relays for ${Math.floor(elapsed / 1000)}s. Exiting.`); process.exit(1); - }); - }, 20000); + } + }, POLL_INTERVAL_MS); } export default AdminInterface; From fb1c239e152c2db8ce567afe495e1461ce49ce6d Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 27 May 2026 20:43:12 +0200 Subject: [PATCH 13/36] fix(#4): re-enable connection watchdog with env-flag opt-out Calls `relayConnectionWatchdog` (introduced in the previous commit) at the end of admin-interface connect(). Gated by NSEC_BUNKER_DISABLE_WATCHDOG=1 for operators who run external liveness checks (Prometheus probes, k8s readiness, etc.) and don't want the daemon to self-terminate. This restores the watchdog behavior that was commented out in commit 42dbbd7 (the emergency stopgap for the old self-echo false positives), but on top of the now-reliable pool-status mechanism. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/admin/index.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/daemon/admin/index.ts b/src/daemon/admin/index.ts index 3940327..db8733b 100644 --- a/src/daemon/admin/index.ts +++ b/src/daemon/admin/index.ts @@ -168,12 +168,17 @@ class AdminInterface { this.handleRequest(req); }); - // pingOrDie disabled — NDK 2.8.1 outbox model doesn't echo - // self-published events back through subscriptions on - // non-public relay channels, so the watchdog fires false - // positives and exits the bunker every 50s on private relays. - // See aiolabs/nsecbunkerd#4 + #7. - // pingOrDie(this.ndk); + // Connection watchdog: exit if pool reports no connected relays + // for >60s so the process supervisor (systemd / docker restart + // policy / k8s) can recover. Replaces the original self-echo + // pingOrDie — see relayConnectionWatchdog comment + #4 + #7. + // Operators with external liveness checking can disable via + // NSEC_BUNKER_DISABLE_WATCHDOG=1. + if (process.env.NSEC_BUNKER_DISABLE_WATCHDOG !== '1') { + relayConnectionWatchdog(this.ndk); + } else { + console.log('⏸ watchdog disabled via NSEC_BUNKER_DISABLE_WATCHDOG=1'); + } }).catch((err) => { console.log('❌ admin connection failed'); console.log(err); From 65a6966b9fb4ddec878037fd1ccddd949060e4a8 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sat, 30 May 2026 12:25:45 +0200 Subject: [PATCH 14/36] fix(#9): close race between create_new_key and NIP-46 connect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two-layer fix for the issue where a fresh client chaining create_new_key + NIP-46 connect on the same target key would time out — bunker had no subscription registered for the new key by the time the connect event arrived at the relay. Layer 1 — run.ts: loadNsec and unlockKey were synchronous and fire-and-forgot the async startKey promise. create_new_key.ts:35 already awaited loadNsec, but the await was a no-op against a sync return. Promoted both to async and properly awaited startKey, so backend.start() at least gets a chance to run before the caller's response goes out. Layer 2 — backend/index.ts: NDKNip46Backend.start() registers the kind-24133 subscription via this.ndk.subscribe(...) but returns immediately, before the relay's EOSE confirms it has the subscription on file. Override start() in our Backend subclass to await EOSE before resolving. This is the actual race-closer — layer 1's await alone wasn't enough because start() was still returning before the relay registered the subscription. Surfaced by aiolabs/lnbits#33's eager-bind chain, which publishes a NIP-46 connect event in the same HTTP round-trip as create_new_key. Pre-fix lnbits deferred the connect to first sign_event (minutes-to-hours after provisioning), so the race window was hidden. Verified end-to-end on bohm regtest: demo account creation through the webapp now completes cleanly, with bunker logs showing connect + sign_event for the freshly-provisioned key. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/backend/index.ts | 37 +++++++++++++++++++++++++++++++++++++ src/daemon/run.ts | 6 +++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/daemon/backend/index.ts b/src/daemon/backend/index.ts index 7661a09..861f10f 100644 --- a/src/daemon/backend/index.ts +++ b/src/daemon/backend/index.ts @@ -22,6 +22,43 @@ export class Backend extends NDKNip46Backend { // this.setStrategy('publish_event', new PublishEventHandlingStrategy()); } + /** + * Override NDKNip46Backend.start() to await the kind-24133 + * subscription's EOSE before resolving. The base implementation + * calls `this.ndk.subscribe(...)` and returns immediately — the + * NDKSubscription queues a REQ on the relay connection but the + * relay's acknowledgement (EOSE) hasn't arrived yet. Any caller + * that publishes a NIP-46 event in the immediate window after + * `start()` returns races against the relay registering this + * subscription. + * + * aiolabs/lnbits#33's eager-bind chain publishes a NIP-46 + * `connect` event in the same HTTP round-trip as `create_new_key`, + * which loses this race deterministically — the bunker never + * sees the connect event because its subscription wasn't yet + * registered with the relay when the event was broadcast. + * + * Awaiting EOSE closes the race: by the time `start()` resolves, + * the relay has confirmed it has the bunker's subscription on + * file and will route matching kind-24133 events to it. + * + * See aiolabs/nsecbunkerd#9 for the full diagnosis. + */ + async start(): Promise { + this.localUser = await this.signer.user(); + await new Promise((resolve) => { + const sub = this.ndk.subscribe( + { + kinds: [24133], + "#p": [this.localUser!.pubkey], + }, + { closeOnEose: false } + ); + sub.on("event", (e: any) => this.handleIncomingEvent(e)); + sub.on("eose", () => resolve()); + }); + } + private async validateToken(token: string) { if (!token) throw new Error("Invalid token"); diff --git a/src/daemon/run.ts b/src/daemon/run.ts index 6637986..89eda0a 100644 --- a/src/daemon/run.ts +++ b/src/daemon/run.ts @@ -257,14 +257,14 @@ class Daemon { const nsec = decryptNsec(iv, data, passphrase); this.activeKeys[keyName] = nsec; - this.startKey(keyName, nsec); + await this.startKey(keyName, nsec); return true; } - loadNsec(keyName: string, nsec: string) { + async loadNsec(keyName: string, nsec: string) { this.activeKeys[keyName] = nsec; - this.startKey(keyName, nsec); + await this.startKey(keyName, nsec); } } \ No newline at end of file From eb6c86a4d1ae8d053bdb1c2115f057bd4015bc99 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sat, 30 May 2026 13:23:52 +0200 Subject: [PATCH 15/36] chore(schema): add Token.revokedAt for surgical token revocation (#11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-requisite for the live-policy auth rewrite in #11. The new revoke_token admin RPC needs a way to mark a single Token as revoked without nuking the whole KeyUser (revoke_user) or conflating with future expiry cleanup (deletedAt). Nullable DateTime — existing rows default to NULL (active), no data migration needed. refs: https://git.atitlan.io/aiolabs/nsecbunkerd/issues/11 --- .../20260530112308_add_token_revoked_at/migration.sql | 2 ++ prisma/schema.prisma | 1 + 2 files changed, 3 insertions(+) create mode 100644 prisma/migrations/20260530112308_add_token_revoked_at/migration.sql diff --git a/prisma/migrations/20260530112308_add_token_revoked_at/migration.sql b/prisma/migrations/20260530112308_add_token_revoked_at/migration.sql new file mode 100644 index 0000000..4dbce97 --- /dev/null +++ b/prisma/migrations/20260530112308_add_token_revoked_at/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Token" ADD COLUMN "revokedAt" DATETIME; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e8b5344..f0072ea 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -110,6 +110,7 @@ model Token { deletedAt DateTime? expiresAt DateTime? redeemedAt DateTime? + revokedAt DateTime? keyUserId Int? policyId Int? policy Policy? @relation(fields: [policyId], references: [id]) From 35826ab695c69f26a63f3ecd66211238e187ee15 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sat, 30 May 2026 13:25:48 +0200 Subject: [PATCH 16/36] feat(acl): live-policy auth in checkIfPubkeyAllowed (#11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shifts sign-time authorization from materialized SigningCondition snapshots (frozen at token-bind time) to a layered model: 1. fetch KeyUser; missing → undefined 2. KeyUser.revokedAt set → false 3. SigningCondition override layer (explicit reject, per-(method, kind) grant/deny) → return matching row's allowed value 4. live policy join: KeyUser → Token (revokedAt IS NULL) → Policy → PolicyRule. Match on method + kind (exact / 'all' / NULL defensive) → true 5. else → undefined (caller may still prompt admin) Backwards-compatible. The existing applyToken fan-out of SigningCondition rows continues to populate step 3 for legacy auth, so already-bound users keep working with no behavior change. New users will still go through that fan-out until the follow-up trim (#12). The key win: PolicyRule mutations via the upcoming companion RPCs (add_policy_rule / remove_policy_rule / etc.) propagate live to every KeyUser bound to that policy, rather than requiring per-user backfill RPCs that don't exist. Algorithm ratified by webapp in https://git.atitlan.io/aiolabs/nsecbunkerd/issues/11#issuecomment-1473. refs: https://git.atitlan.io/aiolabs/nsecbunkerd/issues/11 --- src/daemon/lib/acl/index.ts | 98 +++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 26 deletions(-) diff --git a/src/daemon/lib/acl/index.ts b/src/daemon/lib/acl/index.ts index 42af57d..b32f954 100644 --- a/src/daemon/lib/acl/index.ts +++ b/src/daemon/lib/acl/index.ts @@ -1,13 +1,32 @@ import { NDKEvent, NostrEvent } from '@nostr-dev-kit/ndk'; import prisma from '../../../db.js'; +/** + * Layered authorization check. Order matters: + * + * 1. fetch KeyUser; if missing → undefined (no binding exists) + * 2. if KeyUser.revokedAt set → false (binary user revoke beats everything) + * 3. SigningCondition override layer (per-user grants/denies): + * - explicit reject (method='*', allowed=false) → false + * - matching per-(method,kind) row → return row.allowed + * 4. Live policy join over KeyUser → Token → Policy → PolicyRule + * with Token.revokedAt IS NULL and a matching rule → true + * 5. else → undefined (denied) + * + * Step 3 must precede step 4: per-user denies override the policy, and + * per-user grants extend beyond the policy. Step 2 must precede step 3: + * a revoked KeyUser stays revoked regardless of conditions or policy. + * + * See aiolabs/nsecbunkerd#11 and the issue comment that ratified the + * algorithm (https://git.atitlan.io/aiolabs/nsecbunkerd/issues/11#issuecomment-1473). + */ export async function checkIfPubkeyAllowed( keyName: string, remotePubkey: string, method: IMethod, payload?: string | NostrEvent ): Promise { - // find KeyUser + // Step 1: find KeyUser. const keyUser = await prisma.keyUser.findUnique({ where: { unique_key_user: { keyName, userPubkey: remotePubkey } }, }); @@ -16,9 +35,12 @@ export async function checkIfPubkeyAllowed( return undefined; } - // find SigningCondition - const signingConditionQuery = requestToSigningConditionQuery(method, payload); + // Step 2: binary user revoke. + if (keyUser.revokedAt) { + return false; + } + // Step 3a: explicit-reject override (rejectAllRequestsFromKey writes this). const explicitReject = await prisma.signingCondition.findFirst({ where: { keyUserId: keyUser.id, @@ -32,6 +54,9 @@ export async function checkIfPubkeyAllowed( return false; } + // Step 3b: matching per-(method, kind) override. + const signingConditionQuery = requestToSigningConditionQuery(method, payload); + const signingCondition = await prisma.signingCondition.findFirst({ where: { keyUserId: keyUser.id, @@ -39,32 +64,53 @@ export async function checkIfPubkeyAllowed( } }); - // if no SigningCondition found, return undefined - if (!signingCondition) { - return undefined; - } - - const allowed = signingCondition.allowed; - - // Check if the key user has been revoked - if (allowed) { - const revoked = await prisma.keyUser.findFirst({ - where: { - id: keyUser.id, - revokedAt: { not: null }, - } - }); - - if (revoked) { - return false; - } - } - - if (allowed === true || allowed === false) { + if (signingCondition && (signingCondition.allowed === true || signingCondition.allowed === false)) { console.log(`found signing condition`, signingCondition); - return allowed; + return signingCondition.allowed; } + // Step 4: live policy join. Walk every non-revoked Token bound to this + // KeyUser; if any of their policies has a matching PolicyRule, allow. + // + // PolicyRule.kind matching: + // - exact match against payload kind (stringified — matches the + // create_new_policy.ts:23 storage format `rule.kind.toString()`) + // - 'all' literal matches any kind (parity with the override-layer + // allowScopeToSigningConditionQuery convention) + // - NULL kind is a defensive branch — no current code path inserts + // PolicyRules with null kind, but if one ever appears (raw SQL, + // future code, schema migration) we treat it as a wildcard rather + // than failing closed silently. + const payloadKindString = (method === 'sign_event' && typeof payload === 'object' && payload?.kind !== undefined) + ? payload.kind.toString() + : undefined; + + const kindMatchers: Array<{ kind: string | null }> = [{ kind: null }, { kind: 'all' }]; + if (payloadKindString !== undefined) { + kindMatchers.push({ kind: payloadKindString }); + } + + const policyAllowance = await prisma.token.findFirst({ + where: { + keyUserId: keyUser.id, + revokedAt: null, + policy: { + rules: { + some: { + method, + OR: kindMatchers, + }, + }, + }, + }, + }); + + if (policyAllowance) { + return true; + } + + // Step 5: no override granted, no policy rule matched. Caller's + // requestPermission flow may still prompt the admin out-of-band. return undefined; } From 49091f722ff4d2406d150b6235099b043ec6a331 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sat, 30 May 2026 13:27:28 +0200 Subject: [PATCH 17/36] feat(admin): companion RPCs for live policy + token revocation (#11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six new admin-RPC handlers that complement the live-policy auth rewrite. Each follows the canonical create_new_policy.ts pattern (single JSON-stringified param, kind-24134 response, one prisma mutation, no per-call ACL — validateRequestFromAdmin gates them via the admin-npub allowlist). Policy-level mutations propagate to every KeyUser bound to the policy at the next sign-time check (the point of #11): add_policy_rule { policyId, rule: {method, kind?, maxUsageCount?} } remove_policy_rule { ruleId } update_policy { policyId, patch: {name?, expiresAt?} } Per-KeyUser override mutations (override layer): add_signing_condition { keyUserId, condition: {method, kind?, allowed} } remove_signing_condition { conditionId } Surgical token revocation without nuking the KeyUser: revoke_token { tokenId } The 'all' kind literal is honored as a wildcard in add_policy_rule for parity with the SigningCondition override-layer convention. Param shapes ratified by webapp in https://git.atitlan.io/aiolabs/nsecbunkerd/issues/11#issuecomment-1473. refs: https://git.atitlan.io/aiolabs/nsecbunkerd/issues/11 --- src/daemon/admin/commands/add_policy_rule.ts | 47 +++++++++++++++++++ .../admin/commands/add_signing_condition.ts | 46 ++++++++++++++++++ .../admin/commands/remove_policy_rule.ts | 33 +++++++++++++ .../commands/remove_signing_condition.ts | 26 ++++++++++ src/daemon/admin/commands/revoke_token.ts | 36 ++++++++++++++ src/daemon/admin/commands/update_policy.ts | 43 +++++++++++++++++ src/daemon/admin/index.ts | 12 +++++ 7 files changed, 243 insertions(+) create mode 100644 src/daemon/admin/commands/add_policy_rule.ts create mode 100644 src/daemon/admin/commands/add_signing_condition.ts create mode 100644 src/daemon/admin/commands/remove_policy_rule.ts create mode 100644 src/daemon/admin/commands/remove_signing_condition.ts create mode 100644 src/daemon/admin/commands/revoke_token.ts create mode 100644 src/daemon/admin/commands/update_policy.ts diff --git a/src/daemon/admin/commands/add_policy_rule.ts b/src/daemon/admin/commands/add_policy_rule.ts new file mode 100644 index 0000000..041fd1e --- /dev/null +++ b/src/daemon/admin/commands/add_policy_rule.ts @@ -0,0 +1,47 @@ +import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; +import AdminInterface from "../index.js"; +import prisma from "../../../db.js"; + +/** + * Add a single PolicyRule to an existing Policy. Under the live-policy + * auth model (#11), this propagates to every KeyUser bound to the + * policy at the next sign-time check. + * + * Param shape (JSON-stringified): + * { policyId: number, + * rule: { method: string, + * kind?: number | "all" | null, + * maxUsageCount?: number } } + * + * `kind` is stored as a string for parity with create_new_policy.ts's + * `rule.kind.toString()` storage and the override-layer convention. The + * `'all'` literal is honored at sign-time as a wildcard across kinds. + */ +export default async function addPolicyRule(admin: AdminInterface, req: NDKRpcRequest) { + const [ _payload ] = req.params as [ string ]; + + if (!_payload) throw new Error("Invalid params"); + + const payload = JSON.parse(_payload); + const { policyId, rule } = payload; + + if (typeof policyId !== "number" || !rule || !rule.method) { + throw new Error("Invalid params"); + } + + const policy = await prisma.policy.findUnique({ where: { id: policyId } }); + if (!policy) throw new Error("Policy not found"); + + await prisma.policyRule.create({ + data: { + policyId, + method: rule.method, + kind: rule.kind !== undefined && rule.kind !== null ? rule.kind.toString() : null, + maxUsageCount: rule.maxUsageCount, + currentUsageCount: 0, + } + }); + + const result = JSON.stringify(["ok"]); + return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); +} diff --git a/src/daemon/admin/commands/add_signing_condition.ts b/src/daemon/admin/commands/add_signing_condition.ts new file mode 100644 index 0000000..6cfad88 --- /dev/null +++ b/src/daemon/admin/commands/add_signing_condition.ts @@ -0,0 +1,46 @@ +import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; +import AdminInterface from "../index.js"; +import prisma from "../../../db.js"; + +/** + * Add a SigningCondition override row for a specific KeyUser. Used to + * grant a user a (method, kind) combination beyond the policy, or to + * deny one explicitly even when the policy allows. + * + * Param shape (JSON-stringified): + * { keyUserId: number, + * condition: { method: string, + * kind?: number | "all", + * allowed: boolean } } + * + * The override layer is consulted before the live policy join in + * checkIfPubkeyAllowed (step 3 vs step 4), so `allowed: false` here + * denies regardless of the policy. + */ +export default async function addSigningCondition(admin: AdminInterface, req: NDKRpcRequest) { + const [ _payload ] = req.params as [ string ]; + + if (!_payload) throw new Error("Invalid params"); + + const payload = JSON.parse(_payload); + const { keyUserId, condition } = payload; + + if (typeof keyUserId !== "number" || !condition || !condition.method || typeof condition.allowed !== "boolean") { + throw new Error("Invalid params"); + } + + const keyUser = await prisma.keyUser.findUnique({ where: { id: keyUserId } }); + if (!keyUser) throw new Error("KeyUser not found"); + + await prisma.signingCondition.create({ + data: { + keyUserId, + method: condition.method, + kind: condition.kind !== undefined && condition.kind !== null ? condition.kind.toString() : null, + allowed: condition.allowed, + } + }); + + const result = JSON.stringify(["ok"]); + return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); +} diff --git a/src/daemon/admin/commands/remove_policy_rule.ts b/src/daemon/admin/commands/remove_policy_rule.ts new file mode 100644 index 0000000..b983acd --- /dev/null +++ b/src/daemon/admin/commands/remove_policy_rule.ts @@ -0,0 +1,33 @@ +import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; +import AdminInterface from "../index.js"; +import prisma from "../../../db.js"; + +/** + * Delete a single PolicyRule by id. Under the live-policy auth model + * (#11), removal takes effect at the next sign-time check for every + * KeyUser bound to that policy. + * + * Param shape (JSON-stringified): + * { ruleId: number } + * + * Multi-instance bunker-sharing caveat (per comment 1473 §2): + * downstream reconcilers (e.g. lnbits' lnbits-default policy + * convergence) should treat this as an admin-only op — concurrent + * removes across instance versions can race. Adds are safe, removes + * are not. + */ +export default async function removePolicyRule(admin: AdminInterface, req: NDKRpcRequest) { + const [ _payload ] = req.params as [ string ]; + + if (!_payload) throw new Error("Invalid params"); + + const payload = JSON.parse(_payload); + const { ruleId } = payload; + + if (typeof ruleId !== "number") throw new Error("Invalid params"); + + await prisma.policyRule.delete({ where: { id: ruleId } }); + + const result = JSON.stringify(["ok"]); + return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); +} diff --git a/src/daemon/admin/commands/remove_signing_condition.ts b/src/daemon/admin/commands/remove_signing_condition.ts new file mode 100644 index 0000000..65eff96 --- /dev/null +++ b/src/daemon/admin/commands/remove_signing_condition.ts @@ -0,0 +1,26 @@ +import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; +import AdminInterface from "../index.js"; +import prisma from "../../../db.js"; + +/** + * Delete a SigningCondition override row by id. Used to walk back a + * per-user grant or deny without affecting the policy. + * + * Param shape (JSON-stringified): + * { conditionId: number } + */ +export default async function removeSigningCondition(admin: AdminInterface, req: NDKRpcRequest) { + const [ _payload ] = req.params as [ string ]; + + if (!_payload) throw new Error("Invalid params"); + + const payload = JSON.parse(_payload); + const { conditionId } = payload; + + if (typeof conditionId !== "number") throw new Error("Invalid params"); + + await prisma.signingCondition.delete({ where: { id: conditionId } }); + + const result = JSON.stringify(["ok"]); + return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); +} diff --git a/src/daemon/admin/commands/revoke_token.ts b/src/daemon/admin/commands/revoke_token.ts new file mode 100644 index 0000000..1224d0a --- /dev/null +++ b/src/daemon/admin/commands/revoke_token.ts @@ -0,0 +1,36 @@ +import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; +import AdminInterface from "../index.js"; +import prisma from "../../../db.js"; + +/** + * Revoke a single Token without affecting other tokens for the same + * KeyUser. Sets Token.revokedAt to now; the live-policy auth check + * (#11) filters tokens with `revokedAt IS NULL` so a revoked token's + * policy no longer contributes to any sign-time grant for the + * associated KeyUser. + * + * Param shape (JSON-stringified): + * { tokenId: number } + * + * The KeyUser remains intact and any other (non-revoked) tokens + * bound to it continue to grant via their own policies. Use + * revoke_user for the binary "this user is gone" case. + */ +export default async function revokeToken(admin: AdminInterface, req: NDKRpcRequest) { + const [ _payload ] = req.params as [ string ]; + + if (!_payload) throw new Error("Invalid params"); + + const payload = JSON.parse(_payload); + const { tokenId } = payload; + + if (typeof tokenId !== "number") throw new Error("Invalid params"); + + await prisma.token.update({ + where: { id: tokenId }, + data: { revokedAt: new Date() }, + }); + + const result = JSON.stringify(["ok"]); + return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); +} diff --git a/src/daemon/admin/commands/update_policy.ts b/src/daemon/admin/commands/update_policy.ts new file mode 100644 index 0000000..43028e5 --- /dev/null +++ b/src/daemon/admin/commands/update_policy.ts @@ -0,0 +1,43 @@ +import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; +import AdminInterface from "../index.js"; +import prisma from "../../../db.js"; + +/** + * Update mutable fields on a Policy. Currently `name` and `expiresAt`. + * Other Policy columns (`description`, `deletedAt`, etc.) are not + * exposed by this RPC — they aren't in the ratified shape, and we want + * a single point of intent. + * + * Param shape (JSON-stringified): + * { policyId: number, + * patch: { name?: string, + * expiresAt?: string | null } } + * + * `expiresAt: null` explicitly clears the field; `expiresAt` absent + * from the patch leaves it alone. + */ +export default async function updatePolicy(admin: AdminInterface, req: NDKRpcRequest) { + const [ _payload ] = req.params as [ string ]; + + if (!_payload) throw new Error("Invalid params"); + + const payload = JSON.parse(_payload); + const { policyId, patch } = payload; + + if (typeof policyId !== "number" || !patch || typeof patch !== "object") { + throw new Error("Invalid params"); + } + + const data: { name?: string; expiresAt?: Date | null } = {}; + if (patch.name !== undefined) data.name = patch.name; + if (patch.expiresAt !== undefined) { + data.expiresAt = patch.expiresAt === null ? null : new Date(patch.expiresAt); + } + + if (Object.keys(data).length === 0) throw new Error("Empty patch"); + + await prisma.policy.update({ where: { id: policyId }, data }); + + const result = JSON.stringify(["ok"]); + return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); +} diff --git a/src/daemon/admin/index.ts b/src/daemon/admin/index.ts index db8733b..21e5f23 100644 --- a/src/daemon/admin/index.ts +++ b/src/daemon/admin/index.ts @@ -13,6 +13,12 @@ import createNewToken from './commands/create_new_token'; import unlockKey from './commands/unlock_key'; import renameKeyUser from './commands/rename_key_user.js'; import revokeUser from './commands/revoke_user'; +import addPolicyRule from './commands/add_policy_rule'; +import removePolicyRule from './commands/remove_policy_rule'; +import updatePolicy from './commands/update_policy'; +import addSigningCondition from './commands/add_signing_condition'; +import removeSigningCondition from './commands/remove_signing_condition'; +import revokeToken from './commands/revoke_token'; import fs from 'fs'; import { validateRequestFromAdmin } from './validations/request-from-admin'; import { dmUser } from '../../utils/dm-user'; @@ -202,6 +208,12 @@ class AdminInterface { case 'create_new_policy': await createNewPolicy(this, req); break; case 'get_policies': await this.reqListPolicies(req); break; case 'create_new_token': await createNewToken(this, req); break; + case 'add_policy_rule': await addPolicyRule(this, req); break; + case 'remove_policy_rule': await removePolicyRule(this, req); break; + case 'update_policy': await updatePolicy(this, req); break; + case 'add_signing_condition': await addSigningCondition(this, req); break; + case 'remove_signing_condition': await removeSigningCondition(this, req); break; + case 'revoke_token': await revokeToken(this, req); break; default: const originalKind = req.event.kind!; console.log(`Unknown method ${req.method}`); From 041f431bc2a8d8c4eb206187d568f789fdd02528 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 31 May 2026 12:02:03 +0200 Subject: [PATCH 18/36] =?UTF-8?q?chore(deps):=20bump=20@nostr-dev-kit/ndk?= =?UTF-8?q?=202.8.1=20=E2=86=92=203.0.3=20+=20nostr-tools=20v1=20=E2=86=92?= =?UTF-8?q?=20v2=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NDK 2.8.1 (Apr 2024) is 2 years old and predates NIP-46 backend-side nip44 support. With aiolabs/lnbits#38's phase-2.4 client-side migration to bunker-mediated nip44_*, the bunker's lack of a `nip44_decrypt` strategy registration causes wire RPCs to fall through to `sendResponse(id, remotePubkey, "error", undefined, "Not authorized")` at NDK 2.8.1's backend/index.ts:179. Even nip04 was silently broken: 2.8.1 normalizes the wire method to `encrypt`/`decrypt` for `pubkeyAllowed` while lnbits's policy stores wire names. The encrypt/decrypt path through nsecbunkerd has never actually worked end-to-end; it just hadn't been exercised until phase 2.4 landed. 3.0.3 (Feb 2026) is the current `latest` dist-tag and ships: - `nip44_encrypt` / `nip44_decrypt` backend handlers registered by default + wire-name `pubkeyAllowed` semantics (the immediate fix) - `switch_relays` NIP-46 support for client-side relay migration - Configurable NDKNip46Signer timeout (pairs with lnbits PR #38's matching client-side config) - NIP-44 default outgoing encryption with NIP-04 compat fallback - Async error handling fix in backend dispatch — failed strategies report errors instead of silent drop (deb7f93d) - "Not enough relays received this event" race-condition fix on publish (relevant to open #7 — may close that one too) - Signature verification moved in-house (off legacy nostr-tools v1 path) - 2 years of security/perf updates in transitive @noble/* crypto primitives `nostr-tools` bumped from ^1.17.0 to ^2.17.2 alongside because NDK 3.x's `NDKPrivateKeySigner` imports `finalizeEvent` / `generateSecretKey` + uses the `./nip49` subpath, none of which exist in nostr-tools v1.17. With v1.17 installed, `require('@nostr-dev-kit/ndk')` fails with "Package subpath './nip49' is not defined". Confirmed against the post-install module graph. Source migrations for NDK 3 / nostr-tools v2 API surface land in the follow-up commit; this commit is intentionally just the dep bump so the diff stays reviewable. Refs aiolabs/nsecbunkerd#14 + coord-log 2026-05-31T09:55Z. --- package.json | 4 +- pnpm-lock.yaml | 6887 ++++++++++++++++++++++++++++++------------------ 2 files changed, 4321 insertions(+), 2570 deletions(-) diff --git a/package.json b/package.json index 297fd2a..2a6a4aa 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@fastify/view": "^8.2.0", "@inquirer/password": "^1.1.2", "@inquirer/prompts": "^1.2.3", - "@nostr-dev-kit/ndk": "2.8.1", + "@nostr-dev-kit/ndk": "3.0.3", "@prisma/client": "^5.4.1", "@scure/base": "^1.1.1", "@types/yargs": "^17.0.24", @@ -57,7 +57,7 @@ "isomorphic-ws": "^5.0.0", "lnbits": "^1.1.5", "lnbits-ts": "^0.0.2", - "nostr-tools": "^1.17.0", + "nostr-tools": "^2.17.2", "websocket-polyfill": "^0.0.3", "ws": "^8.13.0", "yargs": "^17.7.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c3fd1d1..f550604 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,1497 +1,1180 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - '@fastify/formbody': - specifier: ^7.4.0 - version: 7.4.0 - '@fastify/view': - specifier: ^8.2.0 - version: 8.2.0 - '@inquirer/password': - specifier: ^1.1.2 - version: 1.1.2 - '@inquirer/prompts': - specifier: ^1.2.3 - version: 1.2.3 - '@nostr-dev-kit/ndk': - specifier: ^2.8.1 - version: 2.8.1(typescript@5.1.3) - '@prisma/client': - specifier: ^5.4.1 - version: 5.4.1(prisma@5.4.1) - '@scure/base': - specifier: ^1.1.1 - version: 1.1.1 - '@types/yargs': - specifier: ^17.0.24 - version: 17.0.24 - axios: - specifier: ^1.6.2 - version: 1.6.2(debug@4.3.4) - bcrypt: - specifier: ^5.1.1 - version: 5.1.1 - crypto-js: - specifier: ^4.2.0 - version: 4.2.0 - debug: - specifier: ^4.3.4 - version: 4.3.4 - dotenv: - specifier: ^16.3.1 - version: 16.3.1 - eslint-config-prettier: - specifier: ^8.8.0 - version: 8.8.0(eslint@8.57.0) - eslint-plugin-import: - specifier: ^2.27.5 - version: 2.27.5(eslint@8.57.0) - eventemitter3: - specifier: ^5.0.1 - version: 5.0.1 - express: - specifier: ^4.18.2 - version: 4.18.2 - fastify: - specifier: ^4.24.3 - version: 4.24.3 - handlebars: - specifier: ^4.7.8 - version: 4.7.8 - isomorphic-ws: - specifier: ^5.0.0 - version: 5.0.0(ws@8.13.0) - lnbits: - specifier: ^1.1.5 - version: 1.1.5(debug@4.3.4) - lnbits-ts: - specifier: ^0.0.2 - version: 0.0.2(debug@4.3.4) - nostr-tools: - specifier: ^1.17.0 - version: 1.17.0(typescript@5.1.3) - websocket-polyfill: - specifier: ^0.0.3 - version: 0.0.3 - ws: - specifier: ^8.13.0 - version: 8.13.0 - yargs: - specifier: ^17.7.2 - version: 17.7.2 +importers: -devDependencies: - '@types/debug': - specifier: ^4.1.8 - version: 4.1.8 - '@types/node': - specifier: ^18.16.18 - version: 18.16.18 - prisma: - specifier: ^5.4.1 - version: 5.4.1 - ts-node: - specifier: ^10.9.1 - version: 10.9.1(@types/node@18.16.18)(typescript@5.1.3) - tsup: - specifier: ^7.2.0 - version: 7.2.0(ts-node@10.9.1)(typescript@5.1.3) - typescript: - specifier: ^5.1.3 - version: 5.1.3 + .: + dependencies: + '@fastify/formbody': + specifier: ^7.4.0 + version: 7.4.0 + '@fastify/view': + specifier: ^8.2.0 + version: 8.2.0 + '@inquirer/password': + specifier: ^1.1.2 + version: 1.1.16 + '@inquirer/prompts': + specifier: ^1.2.3 + version: 1.2.3 + '@nostr-dev-kit/ndk': + specifier: 3.0.3 + version: 3.0.3(nostr-tools@2.23.5(typescript@5.9.3)) + '@prisma/client': + specifier: ^5.4.1 + version: 5.22.0(prisma@5.22.0) + '@scure/base': + specifier: ^1.1.1 + version: 1.2.6 + '@types/yargs': + specifier: ^17.0.24 + version: 17.0.35 + axios: + specifier: ^1.6.2 + version: 1.16.1(debug@4.4.3) + bcrypt: + specifier: ^5.1.1 + version: 5.1.1 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + debug: + specifier: ^4.3.4 + version: 4.4.3 + dotenv: + specifier: ^16.3.1 + version: 16.6.1 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.10.2(eslint@9.39.4) + eslint-plugin-import: + specifier: ^2.27.5 + version: 2.32.0(eslint@9.39.4) + eventemitter3: + specifier: ^5.0.1 + version: 5.0.4 + express: + specifier: ^4.18.2 + version: 4.22.2 + fastify: + specifier: ^4.24.3 + version: 4.29.1 + handlebars: + specifier: ^4.7.8 + version: 4.7.9 + isomorphic-ws: + specifier: ^5.0.0 + version: 5.0.0(ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) + lnbits: + specifier: ^1.1.5 + version: 1.1.5(debug@4.4.3) + lnbits-ts: + specifier: ^0.0.2 + version: 0.0.2(debug@4.4.3) + nostr-tools: + specifier: ^2.17.2 + version: 2.23.5(typescript@5.9.3) + websocket-polyfill: + specifier: ^0.0.3 + version: 0.0.3 + ws: + specifier: ^8.13.0 + version: 8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + yargs: + specifier: ^17.7.2 + version: 17.7.2 + devDependencies: + '@types/debug': + specifier: ^4.1.8 + version: 4.1.13 + '@types/node': + specifier: ^18.16.18 + version: 18.19.130 + prisma: + specifier: ^5.4.1 + version: 5.22.0 + ts-node: + specifier: ^10.9.1 + version: 10.9.2(@types/node@18.19.130)(typescript@5.9.3) + tsup: + specifier: ^7.2.0 + version: 7.3.0(ts-node@10.9.2(@types/node@18.19.130)(typescript@5.9.3))(typescript@5.9.3) + typescript: + specifier: ^5.1.3 + version: 5.9.3 packages: - /@aashutoshrathi/word-wrap@1.2.6: - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - dev: false + '@codesandbox/nodebox@0.1.8': + resolution: {integrity: sha512-2VRS6JDSk+M+pg56GA6CryyUSGPjBEe8Pnae0QL3jJF1mJZJVMDKr93gJRtBbLkfZN6LD/DwMtf+2L0bpWrjqg==} - /@cspotcode/source-map-support@0.8.1: + '@codesandbox/sandpack-client@2.19.8': + resolution: {integrity: sha512-CMV4nr1zgKzVpx4I3FYvGRM5YT0VaQhALMW9vy4wZRhEyWAtJITQIqZzrTGWqB1JvV7V72dVEUCUPLfYz5hgJQ==} + + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - /@esbuild/android-arm64@0.18.20: - resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + '@esbuild/aix-ppc64@0.19.12': + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.19.12': + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} engines: {node: '>=12'} cpu: [arm64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.18.20: - resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + '@esbuild/android-arm@0.19.12': + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} engines: {node: '>=12'} cpu: [arm] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-x64@0.18.20: - resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + '@esbuild/android-x64@0.19.12': + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} engines: {node: '>=12'} cpu: [x64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-arm64@0.18.20: - resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + '@esbuild/darwin-arm64@0.19.12': + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-x64@0.18.20: - resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + '@esbuild/darwin-x64@0.19.12': + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-arm64@0.18.20: - resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + '@esbuild/freebsd-arm64@0.19.12': + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-x64@0.18.20: - resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + '@esbuild/freebsd-x64@0.19.12': + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm64@0.18.20: - resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + '@esbuild/linux-arm64@0.19.12': + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm@0.18.20: - resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + '@esbuild/linux-arm@0.19.12': + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} engines: {node: '>=12'} cpu: [arm] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ia32@0.18.20: - resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + '@esbuild/linux-ia32@0.19.12': + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.18.20: - resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + '@esbuild/linux-loong64@0.19.12': + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-mips64el@0.18.20: - resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + '@esbuild/linux-mips64el@0.19.12': + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ppc64@0.18.20: - resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + '@esbuild/linux-ppc64@0.19.12': + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-riscv64@0.18.20: - resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + '@esbuild/linux-riscv64@0.19.12': + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-s390x@0.18.20: - resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + '@esbuild/linux-s390x@0.19.12': + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-x64@0.18.20: - resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + '@esbuild/linux-x64@0.19.12': + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} engines: {node: '>=12'} cpu: [x64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/netbsd-x64@0.18.20: - resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + '@esbuild/netbsd-x64@0.19.12': + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/openbsd-x64@0.18.20: - resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + '@esbuild/openbsd-x64@0.19.12': + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/sunos-x64@0.18.20: - resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + '@esbuild/sunos-x64@0.19.12': + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} engines: {node: '>=12'} cpu: [x64] os: [sunos] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-arm64@0.18.20: - resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + '@esbuild/win32-arm64@0.19.12': + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-ia32@0.18.20: - resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + '@esbuild/win32-ia32@0.19.12': + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} engines: {node: '>=12'} cpu: [ia32] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-x64@0.18.20: - resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + '@esbuild/win32-x64@0.19.12': + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} engines: {node: '>=12'} cpu: [x64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - dev: false - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: false - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: false + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: false + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@fastify/ajv-compiler@3.5.0: - resolution: {integrity: sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==} - dependencies: - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) - fast-uri: 2.3.0 - dev: false + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@fastify/deepmerge@1.3.0: - resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==} - dev: false + '@eslint/eslintrc@3.3.5': + resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@fastify/error@3.4.1: + '@eslint/js@9.39.4': + resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@fastify/ajv-compiler@3.6.0': + resolution: {integrity: sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==} + + '@fastify/error@3.4.1': resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} - dev: false - /@fastify/fast-json-stringify-compiler@4.3.0: + '@fastify/fast-json-stringify-compiler@4.3.0': resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==} - dependencies: - fast-json-stringify: 5.9.1 - dev: false - /@fastify/formbody@7.4.0: + '@fastify/formbody@7.4.0': resolution: {integrity: sha512-H3C6h1GN56/SMrZS8N2vCT2cZr7mIHzBHzOBa5OPpjfB/D6FzP9mMpE02ZzrFX0ANeh0BAJdoXKOF2e7IbV+Og==} - dependencies: - fast-querystring: 1.1.2 - fastify-plugin: 4.5.1 - dev: false - /@fastify/view@8.2.0: + '@fastify/merge-json-schemas@0.1.1': + resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} + + '@fastify/view@8.2.0': resolution: {integrity: sha512-hBSiBofCnJNlPHEMZWpO1SL84eqOaqujJ1hR3jntFyZZCkweH5jMs12DKYyGesjVll7SJFRRxPUBB8kmUmneRQ==} - dependencies: - fastify-plugin: 4.5.1 - hashlru: 2.3.0 - dev: false - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: false + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} - /@humanwhocodes/module-importer@1.0.1: + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - dev: false - /@humanwhocodes/object-schema@2.0.3: - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - dev: false + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} - /@inquirer/checkbox@1.3.2: - resolution: {integrity: sha512-9ZhpEXiwlXAJ7KvUiDqIy9L4mayOGcP9aDRLT6eiwguuFW1gXQTspteIxk/b6QGger1UXJrtXQpPS7A+PGzVuA==} + '@inquirer/checkbox@1.5.2': + resolution: {integrity: sha512-CifrkgQjDkUkWexmgYYNyB5603HhTHI91vLFeQXh6qrTKiCMVASol01Rs1cv6LP/A2WccZSRlJKZhbaBIs/9ZA==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/core': 2.2.0 - '@inquirer/type': 1.1.0 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - figures: 3.2.0 - dev: false - /@inquirer/confirm@1.0.11: + '@inquirer/confirm@1.0.11': resolution: {integrity: sha512-UWYJ+0dN9rWw0czTPqqKRGLqHsLML9rrQlScn5oOVUtiL2WDTxs95JehP2axKsNkSBMxmFAdA7TdctJkZFJcxA==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/core': 1.3.0 - '@inquirer/type': 1.1.0 - chalk: 4.1.2 - dev: false - /@inquirer/core@1.3.0: + '@inquirer/core@1.3.0': resolution: {integrity: sha512-W7EA48gIMahFLiGW/zF+rgoineqTDK5IQizsOmwvbFfYgiQ8Asetut94THBmB3KnW0nrZL5UPHUK6QzcjEzaCw==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/type': 1.1.0 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-spinners: 2.9.0 - cli-width: 4.0.0 - figures: 3.2.0 - mute-stream: 1.0.0 - run-async: 3.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: false - /@inquirer/core@2.2.0: - resolution: {integrity: sha512-YcSAyRTEJTzitg3yzEGabz0Jwmi8iO9QiLeDVY8LQLzY9AsLouuGRvUZ2Savp1T7AAYCMqDFLQirzB+eSux2Vg==} + '@inquirer/core@6.0.0': + resolution: {integrity: sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/type': 1.1.0 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-spinners: 2.9.0 - cli-width: 4.0.0 - figures: 3.2.0 - mute-stream: 1.0.0 - run-async: 3.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: false - /@inquirer/editor@1.2.1: - resolution: {integrity: sha512-BbmApP63G5bXW7+sLeJUgpeBvu29W5A1rD5BzMO93ChgfSLQRKucICKwZTc+UuJh4eiJ/KpVeVozoyttmV11AA==} + '@inquirer/editor@1.2.15': + resolution: {integrity: sha512-gQ77Ls09x5vKLVNMH9q/7xvYPT6sIs5f7URksw+a2iJZ0j48tVS6crLqm2ugG33tgXHIwiEqkytY60Zyh5GkJQ==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/core': 2.2.0 - '@inquirer/type': 1.1.0 - chalk: 4.1.2 - external-editor: 3.1.0 - dev: false - /@inquirer/expand@1.1.2: - resolution: {integrity: sha512-oa40fTIibTOL6Y7AWPlmimTkA109/tLnqHFQLGfziVfAJNUEWfGDNdL04+l5uOLn+EaBVmdAz1jLzDm9BeLIPQ==} + '@inquirer/expand@1.1.16': + resolution: {integrity: sha512-TGLU9egcuo+s7PxphKUCnJnpCIVY32/EwPCLLuu+gTvYiD8hZgx8Z2niNQD36sa6xcfpdLY6xXDBiL/+g1r2XQ==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/core': 2.2.0 - '@inquirer/type': 1.1.0 - chalk: 4.1.2 - figures: 3.2.0 - dev: false - /@inquirer/input@1.2.2: - resolution: {integrity: sha512-ZMwt3+ov5yQgIWgVhP0vUpGccL/RtH7Nls6vJhPrpA+TaU9KJArSEOWFqQNIXwvsbWjcSO3nE1fIwi63TsLt7Q==} + '@inquirer/input@1.2.16': + resolution: {integrity: sha512-Ou0LaSWvj1ni+egnyQ+NBtfM1885UwhRCMtsRt2bBO47DoC1dwtCa+ZUNgrxlnCHHF0IXsbQHYtIIjFGAavI4g==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/core': 2.2.0 - '@inquirer/type': 1.1.0 - chalk: 4.1.2 - dev: false - /@inquirer/password@1.1.2: - resolution: {integrity: sha512-Rhx7RsU7zB641+Mq2J5VUDYzCacVYVoJrlNRZlQJq5cQQlH4cQZbeH9GeIQarj4ZewTmwP5tBRKgO2lux8bTgg==} + '@inquirer/password@1.1.16': + resolution: {integrity: sha512-aZYZVHLUXZ2gbBot+i+zOJrks1WaiI95lvZCn1sKfcw6MtSSlYC8uDX8sTzQvAsQ8epHoP84UNvAIT0KVGOGqw==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/input': 1.2.2 - '@inquirer/type': 1.1.0 - chalk: 4.1.2 - dev: false - /@inquirer/prompts@1.2.3: + '@inquirer/prompts@1.2.3': resolution: {integrity: sha512-vcPUWXA/boMJc5IDVx/9+ihf1FupsBK1RThnEXnLTpF6hR1iJCoaBoSpREZRdDp/XcPHe/b+QovehBYJoWsUhg==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/checkbox': 1.3.2 - '@inquirer/confirm': 1.0.11 - '@inquirer/core': 1.3.0 - '@inquirer/editor': 1.2.1 - '@inquirer/expand': 1.1.2 - '@inquirer/input': 1.2.2 - '@inquirer/password': 1.1.2 - '@inquirer/rawlist': 1.2.2 - '@inquirer/select': 1.2.2 - dev: false - /@inquirer/rawlist@1.2.2: - resolution: {integrity: sha512-FQZS/8Z1kcYBMbDoqfmMJamE1leO2/SFqsPxEkSdFqdz8VXx/1S8Ldhz7wDNkRUBhIGTTkOxCtNJUsfSwT4vfA==} + '@inquirer/rawlist@1.2.16': + resolution: {integrity: sha512-pZ6TRg2qMwZAOZAV6TvghCtkr53dGnK29GMNQ3vMZXSNguvGqtOVc4j/h1T8kqGJFagjyfBZhUPGwNS55O5qPQ==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/core': 2.2.0 - '@inquirer/type': 1.1.0 - chalk: 4.1.2 - dev: false - /@inquirer/select@1.2.2: - resolution: {integrity: sha512-asiP4Ej4AR0uWsQt8/ajAtF5IjBuTZ/YQgn/Xk7kviWN/wuFfUBo0dYntr0/rSvhNyt0jY6/yDhMM6mSPFLHRg==} + '@inquirer/select@1.3.3': + resolution: {integrity: sha512-RzlRISXWqIKEf83FDC9ZtJ3JvuK1l7aGpretf41BCWYrvla2wU8W8MTRNMiPrPJ+1SIqrRC1nZdZ60hD9hRXLg==} engines: {node: '>=14.18.0'} - dependencies: - '@inquirer/core': 2.2.0 - '@inquirer/type': 1.1.0 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - figures: 3.2.0 - dev: false - /@inquirer/type@1.1.0: - resolution: {integrity: sha512-XMaorygt2o/mXinZg/OOz6d3JKuV3o4jRc/3KDiVPeKLLkjiO4iJErbLKtKn+Od2ZC2lbiFQkrIuloVpEubisA==} - engines: {node: '>=14.18.0'} - dev: false + '@inquirer/type@1.5.5': + resolution: {integrity: sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==} + engines: {node: '>=18'} - /@jridgewell/gen-mapping@0.3.3: - resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.9 - dev: true - /@jridgewell/resolve-uri@3.1.1: - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} - engines: {node: '>=6.0.0'} - dev: true + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - /@jridgewell/set-array@1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} - dev: true + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true - - /@jridgewell/trace-mapping@0.3.9: + '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - /@mapbox/node-pre-gyp@1.0.11: + '@mapbox/node-pre-gyp@1.0.11': resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true - dependencies: - detect-libc: 2.0.2 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.5.4 - tar: 6.2.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: false - /@noble/ciphers@0.2.0: - resolution: {integrity: sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==} - dev: false + '@noble/ciphers@2.1.1': + resolution: {integrity: sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw==} + engines: {node: '>= 20.19.0'} - /@noble/curves@1.1.0: - resolution: {integrity: sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==} - dependencies: - '@noble/hashes': 1.3.1 - dev: false + '@noble/curves@1.9.7': + resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} + engines: {node: ^14.21.3 || >=16} - /@noble/curves@1.4.0: - resolution: {integrity: sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==} - dependencies: - '@noble/hashes': 1.4.0 - dev: false + '@noble/curves@2.0.1': + resolution: {integrity: sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==} + engines: {node: '>= 20.19.0'} - /@noble/hashes@1.3.1: - resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} - engines: {node: '>= 16'} - dev: false + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} - /@noble/hashes@1.3.2: - resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} - engines: {node: '>= 16'} - dev: false + '@noble/hashes@2.0.1': + resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==} + engines: {node: '>= 20.19.0'} - /@noble/hashes@1.4.0: - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - dev: false + '@noble/secp256k1@2.3.0': + resolution: {integrity: sha512-0TQed2gcBbIrh7Ccyw+y/uZQvbJwm7Ao4scBUxqpBCcsOlZG0O4KGfjtNAy/li4W8n1xt3dxrwJ0beZ2h2G6Kw==} - /@noble/secp256k1@2.1.0: - resolution: {integrity: sha512-XLEQQNdablO0XZOIniFQimiXsZDNwaYgL96dZwC54Q30imSbAOFf3NKtepc+cXyuZf5Q1HCgbqgZ2UFFuHVcEw==} - dev: false - - /@nodelib/fs.scandir@2.1.5: + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - /@nodelib/fs.stat@2.0.5: + '@nodelib/fs.stat@2.0.5': resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - /@nodelib/fs.walk@1.2.8: + '@nodelib/fs.walk@1.2.8': resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.15.0 - /@nostr-dev-kit/ndk@2.8.1(typescript@5.1.3): - resolution: {integrity: sha512-2WPN1FVhxcLxFYwva2Ti6XKQUjqU0jfdoHHhqDF+0Mxp8f/uDyLflsUQCXsZym5rOIHY85eCYhAXi6V6q6gpRg==} - dependencies: - '@noble/curves': 1.4.0 - '@noble/hashes': 1.4.0 - '@noble/secp256k1': 2.1.0 - '@scure/base': 1.1.1 - debug: 4.3.4 - light-bolt11-decoder: 3.1.1 - node-fetch: 3.3.2 - nostr-tools: 1.17.0(typescript@5.1.3) - tseep: 1.2.1 - typescript-lru-cache: 2.0.0 - utf8-buffer: 1.0.0 - websocket-polyfill: 0.0.3 - transitivePeerDependencies: - - supports-color - - typescript - dev: false + '@nostr-dev-kit/ndk@3.0.3': + resolution: {integrity: sha512-wGQOnvpKjhkq/j0pnRGTiHyrujww7N/iJQKOBrjsIxqTvcy6iyqh/3TijTKlaapdvexx2E2xCn9X+q0dxxISug==} + engines: {node: '>=16'} + peerDependencies: + nostr-tools: ^2.17.2 - /@prisma/client@5.4.1(prisma@5.4.1): - resolution: {integrity: sha512-xyD0DJ3gRNfLbPsC+YfMBBuLJtZKQfy1OD2qU/PZg+HKrr7SO+09174LMeTlWP0YF2wca9LxtVd4HnAiB5ketQ==} + '@open-draft/deferred-promise@2.2.0': + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + + '@prisma/client@5.22.0': + resolution: {integrity: sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==} engines: {node: '>=16.13'} - requiresBuild: true peerDependencies: prisma: '*' peerDependenciesMeta: prisma: optional: true - dependencies: - '@prisma/engines-version': 5.4.1-1.2f302df92bd8945e20ad4595a73def5b96afa54f - prisma: 5.4.1 - dev: false - /@prisma/engines-version@5.4.1-1.2f302df92bd8945e20ad4595a73def5b96afa54f: - resolution: {integrity: sha512-+nUQM/y8C+1GG5Ioeqcu6itFslCfxvQSAUVSMC9XM2G2Fcq0F4Afnp6m0pXF6X6iUBWen7jZBPmM9Qlq4Nr3/A==} - dev: false + '@prisma/debug@5.22.0': + resolution: {integrity: sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==} - /@prisma/engines@5.4.1: - resolution: {integrity: sha512-vJTdY4la/5V3N7SFvWRmSMUh4mIQnyb/MNoDjzVbh9iLmEC+uEykj/1GPviVsorvfz7DbYSQC4RiwmlEpTEvGA==} - requiresBuild: true + '@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2': + resolution: {integrity: sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==} - /@scure/base@1.1.1: + '@prisma/engines@5.22.0': + resolution: {integrity: sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==} + + '@prisma/fetch-engine@5.22.0': + resolution: {integrity: sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==} + + '@prisma/get-platform@5.22.0': + resolution: {integrity: sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==} + + '@rollup/rollup-android-arm-eabi@4.60.4': + resolution: {integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.60.4': + resolution: {integrity: sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.60.4': + resolution: {integrity: sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.60.4': + resolution: {integrity: sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.60.4': + resolution: {integrity: sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.60.4': + resolution: {integrity: sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.60.4': + resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.60.4': + resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.60.4': + resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.60.4': + resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.60.4': + resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.60.4': + resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.60.4': + resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.60.4': + resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.60.4': + resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.60.4': + resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.60.4': + resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.60.4': + resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.60.4': + resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.60.4': + resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.60.4': + resolution: {integrity: sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.60.4': + resolution: {integrity: sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.60.4': + resolution: {integrity: sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.60.4': + resolution: {integrity: sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.60.4': + resolution: {integrity: sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==} + cpu: [x64] + os: [win32] + + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + + '@scure/base@1.1.1': resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==} - dev: false - /@scure/bip32@1.3.1: - resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==} - dependencies: - '@noble/curves': 1.1.0 - '@noble/hashes': 1.3.2 - '@scure/base': 1.1.1 - dev: false + '@scure/base@1.2.6': + resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} - /@scure/bip39@1.2.1: - resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} - dependencies: - '@noble/hashes': 1.3.2 - '@scure/base': 1.1.1 - dev: false + '@scure/base@2.0.0': + resolution: {integrity: sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w==} - /@tsconfig/node10@1.0.9: - resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true + '@scure/bip32@2.0.1': + resolution: {integrity: sha512-4Md1NI5BzoVP+bhyJaY3K6yMesEFzNS1sE/cP+9nuvE7p/b0kx9XbpDHHFl8dHtufcbdHRUUQdRqLIPHN/s7yA==} - /@tsconfig/node12@1.0.11: + '@scure/bip39@2.0.1': + resolution: {integrity: sha512-PsxdFj/d2AcJcZDX1FXN3dDgitDDTmwf78rKZq1a6c1P1Nan1X/Sxc7667zU3U+AN60g7SxxP0YCVw2H/hBycg==} + + '@shikijs/core@3.23.0': + resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==} + + '@shikijs/engine-javascript@3.23.0': + resolution: {integrity: sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==} + + '@shikijs/engine-oniguruma@3.23.0': + resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==} + + '@shikijs/langs@3.23.0': + resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} + + '@shikijs/themes@3.23.0': + resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} + + '@shikijs/types@3.23.0': + resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@tsconfig/node10@1.0.12': + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + + '@tsconfig/node12@1.0.11': resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - /@tsconfig/node14@1.0.3: + '@tsconfig/node14@1.0.3': resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - /@tsconfig/node16@1.0.4: + '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true - /@types/debug@4.1.8: - resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==} - dependencies: - '@types/ms': 0.7.31 - dev: true + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} - /@types/json5@0.0.29: + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: false - /@types/ms@0.7.31: - resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} - dev: true + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - /@types/node@18.16.18: - resolution: {integrity: sha512-/aNaQZD0+iSBAGnvvN2Cx92HqE5sZCPZtx2TsK+4nvV23fFe09jVDvpArXr2j9DnYlzuU9WuoykDDc6wqvpNcw==} - dev: true + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - /@types/yargs-parser@21.0.0: - resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} - dev: false + '@types/mute-stream@0.0.4': + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} - /@types/yargs@17.0.24: - resolution: {integrity: sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==} - dependencies: - '@types/yargs-parser': 21.0.0 - dev: false + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: false + '@types/node@20.19.41': + resolution: {integrity: sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==} - /abbrev@1.1.1: + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/wrap-ansi@3.0.0': + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + '@ungap/structured-clone@1.3.1': + resolution: {integrity: sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==} + + abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: false - /abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - dependencies: - event-target-shim: 5.0.1 - dev: false - - /abstract-logging@2.0.1: + abstract-logging@2.0.1: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} - dev: false - /accepts@1.3.8: + accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: false - /acorn-jsx@5.3.2(acorn@8.11.3): + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.3 - dev: false - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} engines: {node: '>=0.4.0'} - dev: true - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} hasBin: true - dev: false - /acorn@8.9.0: - resolution: {integrity: sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /agent-base@6.0.2: + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false - /ajv-formats@2.1.1(ajv@8.12.0): + ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: ajv: ^8.0.0 peerDependenciesMeta: ajv: optional: true - dependencies: - ajv: 8.12.0 - dev: false - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: false + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true - /ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: false + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} - /ansi-escapes@4.3.2: + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: false - /ansi-regex@5.0.1: + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - dev: false - /ansi-styles@4.3.0: + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: false - /any-promise@1.3.0: + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: true - /anymatch@3.1.3: + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - /aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - dev: false + aproba@2.1.0: + resolution: {integrity: sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==} - /archy@1.0.0: - resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} - dev: false - - /are-we-there-yet@2.0.0: + are-we-there-yet@2.0.0: resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} engines: {node: '>=10'} - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - dev: false + deprecated: This package is no longer supported. - /arg@4.1.3: + arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - /argparse@2.0.1: + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: false - /array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} - dependencies: - call-bind: 1.0.2 - is-array-buffer: 3.0.2 - dev: false - - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: false - - /array-includes@3.1.6: - resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - get-intrinsic: 1.2.1 - is-string: 1.0.7 - dev: false - /array-union@2.1.0: + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - dev: true - /array.prototype.flat@1.3.1: - resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} + array.prototype.findlastindex@1.2.6: + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - es-shim-unscopables: 1.0.0 - dev: false - /array.prototype.flatmap@1.3.1: - resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - es-shim-unscopables: 1.0.0 - dev: false - /asynckit@0.4.0: + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: false - /atomic-sleep@1.0.0: + atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} - dev: false - /available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - dev: false - /avvio@8.2.1: - resolution: {integrity: sha512-TAlMYvOuwGyLK3PfBb5WKBXZmXz2fVCgv23d6zZFdle/q3gPjmxBaeuC0pY0Dzs5PWMSgfqqEZkrye19GlDTgw==} - dependencies: - archy: 1.0.0 - debug: 4.3.4 - fastq: 1.15.0 - transitivePeerDependencies: - - supports-color - dev: false + avvio@8.4.0: + resolution: {integrity: sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==} - /axios@0.21.4(debug@4.3.4): + axios@0.21.4: resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} - dependencies: - follow-redirects: 1.15.3(debug@4.3.4) - transitivePeerDependencies: - - debug - dev: false - /axios@1.6.2(debug@4.3.4): - resolution: {integrity: sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==} - dependencies: - follow-redirects: 1.15.3(debug@4.3.4) - form-data: 4.0.0 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - dev: false + axios@1.16.1: + resolution: {integrity: sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==} - /balanced-match@1.0.2: + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - /base64-js@1.5.1: + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: false - /bcrypt@5.1.1: + bcrypt@5.1.1: resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==} engines: {node: '>= 10.0.0'} - requiresBuild: true - dependencies: - '@mapbox/node-pre-gyp': 1.0.11 - node-addon-api: 5.1.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: false - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - dev: true - /body-parser@1.20.1: - resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + body-parser@1.20.5: + resolution: {integrity: sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.1 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 + brace-expansion@1.1.15: + resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==} - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - /buffer@6.0.3: + buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: false - /bufferutil@4.0.7: - resolution: {integrity: sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==} + bufferutil@4.1.0: + resolution: {integrity: sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==} engines: {node: '>=6.14.2'} - requiresBuild: true - dependencies: - node-gyp-build: 4.6.0 - dev: false - /bundle-require@4.0.2(esbuild@0.18.20): - resolution: {integrity: sha512-jwzPOChofl67PSTW2SGubV9HBQAhhR2i6nskiOThauo9dzwDUgOWQScFVaJkjEfYX+UXiD+LEx8EblQMc2wIag==} + bundle-require@4.2.1: + resolution: {integrity: sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} peerDependencies: esbuild: '>=0.17' - dependencies: - esbuild: 0.18.20 - load-tsconfig: 0.2.5 - dev: true - /bytes@3.1.2: + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} - dev: false - /cac@6.7.14: + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - dev: true - /call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} - dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.2.1 - dev: false + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} - /callsites@3.1.0: + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: false - /chalk@4.1.2: + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: false - /chardet@0.7.0: + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: false - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - /chownr@2.0.0: + chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} - dev: false - /cli-spinners@2.9.0: - resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==} + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} - dev: false - /cli-width@4.0.0: - resolution: {integrity: sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==} + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} - dev: false - /cliui@8.0.1: + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: false - /color-convert@2.0.1: + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: false - /color-name@1.1.4: + color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: false - /color-support@1.1.3: + color-support@1.1.3: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true - dev: false - /combined-stream@1.0.8: + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: false - /commander@4.1.1: + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} - dev: true - /concat-map@0.0.1: + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - /console-control-strings@1.1.0: + console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - dev: false - /content-disposition@0.5.4: + content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - dev: false - /content-type@1.0.5: + content-type@1.0.5: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - dev: false - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: false + cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} - /cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} - dev: false - /create-require@1.1.1: + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - /crypto-js@4.2.0: + crypto-js@4.2.0: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} - dev: false - /d@1.0.1: - resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} - dependencies: - es5-ext: 0.10.62 - type: 1.2.0 - dev: false + d@1.0.2: + resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} + engines: {node: '>=0.12'} - /data-uri-to-buffer@4.0.1: - resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} - engines: {node: '>= 12'} - dev: false + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} - /debug@2.6.9: + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: supports-color: '*' peerDependenciesMeta: supports-color: optional: true - dependencies: - ms: 2.0.0 - dev: false - /debug@3.2.7: + debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: supports-color: '*' peerDependenciesMeta: supports-color: optional: true - dependencies: - ms: 2.1.3 - dev: false - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' peerDependenciesMeta: supports-color: optional: true - dependencies: - ms: 2.1.2 - /deep-is@0.1.4: + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: false - /define-properties@1.2.0: - resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} - dependencies: - has-property-descriptors: 1.0.0 - object-keys: 1.1.1 - dev: false - /delayed-stream@1.0.0: + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - dev: false - /delegates@1.0.0: + delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - dev: false - /depd@2.0.0: + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} - dev: false - /destroy@1.2.0: + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: false - /detect-libc@2.0.2: - resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - dev: false - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff@4.0.4: + resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} engines: {node: '>=0.3.1'} - dev: true - /dir-glob@3.0.1: + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - /doctrine@2.1.0: + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: false - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: false - - /dotenv@16.3.1: - resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} - dev: false - /ee-first@1.1.1: + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: false - /emoji-regex@8.0.0: + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: false - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} - dev: false - /es-abstract@1.21.2: - resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} + es-abstract@1.24.2: + resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.0 - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - es-set-tostringtag: 2.0.1 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.5 - get-intrinsic: 1.2.1 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 - gopd: 1.0.1 - has: 1.0.3 - has-property-descriptors: 1.0.0 - has-proto: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.5 - is-array-buffer: 3.0.2 - is-callable: 1.2.7 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-typed-array: 1.1.10 - is-weakref: 1.0.2 - object-inspect: 1.12.3 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.5.0 - safe-regex-test: 1.0.0 - string.prototype.trim: 1.2.7 - string.prototype.trimend: 1.0.6 - string.prototype.trimstart: 1.0.6 - typed-array-length: 1.0.4 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.9 - dev: false - /es-set-tostringtag@2.0.1: - resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.1 - has: 1.0.3 - has-tostringtag: 1.0.0 - dev: false - /es-shim-unscopables@1.0.0: - resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} - dependencies: - has: 1.0.3 - dev: false - - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: false - /es5-ext@0.10.62: - resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + es5-ext@0.10.64: + resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} engines: {node: '>=0.10'} - requiresBuild: true - dependencies: - es6-iterator: 2.0.3 - es6-symbol: 3.1.3 - next-tick: 1.1.0 - dev: false - /es6-iterator@2.0.3: + es6-iterator@2.0.3: resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} - dependencies: - d: 1.0.1 - es5-ext: 0.10.62 - es6-symbol: 3.1.3 - dev: false - /es6-symbol@3.1.3: - resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} - dependencies: - d: 1.0.1 - ext: 1.7.0 - dev: false + es6-symbol@3.1.4: + resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} + engines: {node: '>=0.12'} - /esbuild@0.18.20: - resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} engines: {node: '>=12'} hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.18.20 - '@esbuild/android-arm64': 0.18.20 - '@esbuild/android-x64': 0.18.20 - '@esbuild/darwin-arm64': 0.18.20 - '@esbuild/darwin-x64': 0.18.20 - '@esbuild/freebsd-arm64': 0.18.20 - '@esbuild/freebsd-x64': 0.18.20 - '@esbuild/linux-arm': 0.18.20 - '@esbuild/linux-arm64': 0.18.20 - '@esbuild/linux-ia32': 0.18.20 - '@esbuild/linux-loong64': 0.18.20 - '@esbuild/linux-mips64el': 0.18.20 - '@esbuild/linux-ppc64': 0.18.20 - '@esbuild/linux-riscv64': 0.18.20 - '@esbuild/linux-s390x': 0.18.20 - '@esbuild/linux-x64': 0.18.20 - '@esbuild/netbsd-x64': 0.18.20 - '@esbuild/openbsd-x64': 0.18.20 - '@esbuild/sunos-x64': 0.18.20 - '@esbuild/win32-arm64': 0.18.20 - '@esbuild/win32-ia32': 0.18.20 - '@esbuild/win32-x64': 0.18.20 - dev: true - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} - dev: false - /escape-html@1.0.3: + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: false - /escape-string-regexp@1.0.5: + escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} - dev: false - /escape-string-regexp@4.0.0: + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - dev: false - /eslint-config-prettier@8.8.0(eslint@8.57.0): - resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} + eslint-config-prettier@8.10.2: + resolution: {integrity: sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==} hasBin: true peerDependencies: eslint: '>=7.0.0' - dependencies: - eslint: 8.57.0 - dev: false - /eslint-import-resolver-node@0.3.7: - resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} - dependencies: - debug: 3.2.7 - is-core-module: 2.12.1 - resolve: 1.22.2 - transitivePeerDependencies: - - supports-color - dev: false + eslint-import-resolver-node@0.3.10: + resolution: {integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==} - /eslint-module-utils@2.8.0(eslint-import-resolver-node@0.3.7)(eslint@8.57.0): - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + eslint-module-utils@2.13.0: + resolution: {integrity: sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -1510,1150 +1193,687 @@ packages: optional: true eslint-import-resolver-webpack: optional: true - dependencies: - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.7 - transitivePeerDependencies: - - supports-color - dev: false - /eslint-plugin-import@2.27.5(eslint@8.57.0): - resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} + eslint-plugin-import@2.32.0: + resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 peerDependenciesMeta: '@typescript-eslint/parser': optional: true - dependencies: - array-includes: 3.1.6 - array.prototype.flat: 1.3.1 - array.prototype.flatmap: 1.3.1 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.8.0(eslint-import-resolver-node@0.3.7)(eslint@8.57.0) - has: 1.0.3 - is-core-module: 2.12.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.values: 1.1.6 - resolve: 1.22.2 - semver: 6.3.0 - tsconfig-paths: 3.14.2 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: false - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: false + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /eslint-visitor-keys@3.4.3: + eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: false - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.39.4: + resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: false + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - dev: false - - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + esniff@2.0.1: + resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: false - /esrecurse@4.3.0: + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: false - /estraverse@5.3.0: + estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - dev: false - /esutils@2.0.3: + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - dev: false - /etag@1.8.1: + etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} - dev: false - /event-target-shim@5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - dev: false + event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} - /eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - dev: false + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} - /events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - dev: false - - /execa@5.1.1: + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - /express@4.18.2: - resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + express@4.22.2: + resolution: {integrity: sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==} engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.1 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.5.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: false - /ext@1.7.0: + ext@1.7.0: resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} - dependencies: - type: 2.7.2 - dev: false - /external-editor@3.1.0: + external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - dev: false - /fast-content-type-parse@1.1.0: + fast-content-type-parse@1.1.0: resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} - dev: false - /fast-decode-uri-component@1.0.1: + fast-decode-uri-component@1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} - dev: false - /fast-deep-equal@3.1.3: + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: false - /fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - /fast-json-stable-stringify@2.1.0: + fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: false - /fast-json-stringify@5.9.1: - resolution: {integrity: sha512-NMrf+uU9UJnTzfxaumMDXK1NWqtPCfGoM9DYIE+ESlaTQqjlANFBy0VAbsm6FB88Mx0nceyi18zTo5kIEUlzxg==} - dependencies: - '@fastify/deepmerge': 1.3.0 - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) - fast-deep-equal: 3.1.3 - fast-uri: 2.3.0 - json-schema-ref-resolver: 1.0.1 - rfdc: 1.3.0 - dev: false + fast-json-stringify@5.16.1: + resolution: {integrity: sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==} - /fast-levenshtein@2.0.6: + fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: false - /fast-querystring@1.1.2: + fast-querystring@1.1.2: resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} - dependencies: - fast-decode-uri-component: 1.0.1 - dev: false - /fast-redact@3.3.0: - resolution: {integrity: sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==} - engines: {node: '>=6'} - dev: false + fast-uri@2.4.0: + resolution: {integrity: sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==} - /fast-uri@2.3.0: - resolution: {integrity: sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==} - dev: false + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} - /fastify-plugin@4.5.1: + fastify-plugin@4.5.1: resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} - dev: false - /fastify@4.24.3: - resolution: {integrity: sha512-6HHJ+R2x2LS3y1PqxnwEIjOTZxFl+8h4kSC/TuDPXtA+v2JnV9yEtOsNSKK1RMD7sIR2y1ZsA4BEFaid/cK5pg==} - dependencies: - '@fastify/ajv-compiler': 3.5.0 - '@fastify/error': 3.4.1 - '@fastify/fast-json-stringify-compiler': 4.3.0 - abstract-logging: 2.0.1 - avvio: 8.2.1 - fast-content-type-parse: 1.1.0 - fast-json-stringify: 5.9.1 - find-my-way: 7.7.0 - light-my-request: 5.11.0 - pino: 8.16.2 - process-warning: 2.3.1 - proxy-addr: 2.0.7 - rfdc: 1.3.0 - secure-json-parse: 2.7.0 - semver: 7.5.4 - toad-cache: 3.3.1 - transitivePeerDependencies: - - supports-color - dev: false + fastify@4.29.1: + resolution: {integrity: sha512-m2kMNHIG92tSNWv+Z3UeTR9AWLLuo7KctC7mlFPtMEVrfjIhmQhkQnT9v15qA/BfVq3vvj134Y0jl9SBje3jXQ==} - /fastq@1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} - dependencies: - reusify: 1.0.4 + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} - /fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.3.3 - dev: false + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true - /figures@3.2.0: + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} - dependencies: - escape-string-regexp: 1.0.5 - dev: false - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.2.0 - dev: false + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + finalhandler@1.3.2: + resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - /find-my-way@7.7.0: - resolution: {integrity: sha512-+SrHpvQ52Q6W9f3wJoJBbAQULJuNEEQwBvlvYwACDhBTLOTMiQ0HYWh4+vC3OivGP2ENcTI1oKlFA2OepJNjhQ==} + find-my-way@8.2.2: + resolution: {integrity: sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA==} engines: {node: '>=14'} - dependencies: - fast-deep-equal: 3.1.3 - fast-querystring: 1.1.2 - safe-regex2: 2.0.0 - dev: false - /find-up@5.0.0: + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: false - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - dev: false + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: false + flatted@3.4.2: + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} - /follow-redirects@1.15.3(debug@4.3.4): - resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} engines: {node: '>=4.0'} peerDependencies: debug: '*' peerDependenciesMeta: debug: optional: true - dependencies: - debug: 4.3.4 - dev: false - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: false + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} - /form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: false - /formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} - dependencies: - fetch-blob: 3.2.0 - dev: false - - /forwarded@0.2.0: + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} - dev: false - /fresh@0.5.2: + fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} - dev: false - /fs-minipass@2.1.0: + fs-minipass@2.1.0: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: false - /fs.realpath@1.0.0: + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - /fsevents@2.3.3: + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - requiresBuild: true - dev: true - optional: true - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: false + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - /function.prototype.name@1.1.5: - resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - functions-have-names: 1.2.3 - dev: false - /functions-have-names@1.2.3: + functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: false - /gauge@3.0.2: + gauge@3.0.2: resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} engines: {node: '>=10'} - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: false + deprecated: This package is no longer supported. - /get-caller-file@2.0.5: + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - dev: false - /get-intrinsic@1.2.1: - resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} - dependencies: - function-bind: 1.1.1 - has: 1.0.3 - has-proto: 1.0.1 - has-symbols: 1.0.3 - dev: false + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} - /get-stream@6.0.1: + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - dev: true - /get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - dev: false - /glob-parent@5.1.2: + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - /glob-parent@6.0.2: + glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: false - /glob@7.1.6: - resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /glob@7.2.3: + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: false + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: false + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.0 - dev: false - /globby@11.1.0: + globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.1 - ignore: 5.2.4 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.1 - dev: false + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: false - - /handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + handlebars@4.7.9: + resolution: {integrity: sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==} engines: {node: '>=0.4.7'} hasBin: true - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.17.4 - dev: false - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: false + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} - /has-flag@4.0.0: + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - dev: false - /has-property-descriptors@1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} - dependencies: - get-intrinsic: 1.2.1 - dev: false + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} engines: {node: '>= 0.4'} - dev: false - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} - dev: false - /has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: false - /has-unicode@2.0.1: + has-unicode@2.0.1: resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - dev: false - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.1 - dev: false - - /hashlru@2.3.0: + hashlru@2.3.0: resolution: {integrity: sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==} - dev: false - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: false - /https-proxy-agent@5.0.1: + https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false - /human-signals@2.1.0: + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - dev: true - /iconv-lite@0.4.24: + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: false - /ieee754@1.2.1: + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: false - /ignore@5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - dev: true - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: false - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: false - /imurmurhash@0.1.4: + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - dev: false - /inflight@1.0.6: + inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - /inherits@2.0.4: + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - /internal-slot@1.0.5: - resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.1 - has: 1.0.3 - side-channel: 1.0.4 - dev: false - /ipaddr.js@1.9.1: + ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - dev: false - /is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - is-typed-array: 1.1.10 - dev: false + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: false + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} - /is-binary-path@2.1.0: + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - dev: true - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: false - /is-callable@1.2.7: + is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - dev: false - /is-core-module@2.12.1: - resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} - dependencies: - has: 1.0.3 - dev: false - - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: false - /is-extglob@2.1.1: + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - /is-fullwidth-code-point@3.0.0: + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - dev: false - /is-glob@4.0.3: + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - /is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} - dev: false - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: false - /is-number@7.0.0: + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - dev: true - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: false - - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: false - /is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - dependencies: - call-bind: 1.0.2 - dev: false + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} - /is-stream@2.0.1: + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - dev: true - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: false - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: false - /is-typed-array@1.1.10: - resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - dev: false - /is-typedarray@1.0.0: + is-typedarray@1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - dev: false - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.2 - dev: false + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} - /isexe@2.0.0: + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - /isomorphic-ws@5.0.0(ws@8.13.0): + isomorphic-ws@5.0.0: resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} peerDependencies: ws: '*' - dependencies: - ws: 8.13.0 - dev: false - /joycon@3.1.1: + joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} - dev: true - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true - dependencies: - argparse: 2.0.1 - dev: false - /json-buffer@3.0.1: + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: false - /json-schema-ref-resolver@1.0.1: + json-schema-ref-resolver@1.0.1: resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} - dependencies: - fast-deep-equal: 3.1.3 - dev: false - /json-schema-traverse@0.4.1: + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: false - /json-schema-traverse@1.0.0: + json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: false - /json-stable-stringify-without-jsonify@1.0.1: + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: false - /json5@1.0.2: + json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true - dependencies: - minimist: 1.2.8 - dev: false - /keyv@4.5.4: + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: false - /levn@0.4.1: + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: false - /light-bolt11-decoder@3.1.1: - resolution: {integrity: sha512-sLg/KCwYkgsHWkefWd6KqpCHrLFWWaXTOX3cf6yD2hAzL0SLpX+lFcaFK2spkjbgzG6hhijKfORDc9WoUHwX0A==} - dependencies: - '@scure/base': 1.1.1 - dev: false + light-bolt11-decoder@3.2.0: + resolution: {integrity: sha512-3QEofgiBOP4Ehs9BI+RkZdXZNtSys0nsJ6fyGeSiAGCBsMwHGUDS/JQlY/sTnWs91A2Nh0S9XXfA8Sy9g6QpuQ==} - /light-my-request@5.11.0: - resolution: {integrity: sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==} - dependencies: - cookie: 0.5.0 - process-warning: 2.3.1 - set-cookie-parser: 2.6.0 - dev: false + light-my-request@5.14.0: + resolution: {integrity: sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==} - /lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - dev: true + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} - /lines-and-columns@1.2.4: + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - /lnbits-ts@0.0.2(debug@4.3.4): + lnbits-ts@0.0.2: resolution: {integrity: sha512-3OnkL/IILpPQ0SUkN1kBdAO1dBmV+QqQNIh1GSz3koBqwjnFM8+RoZDKMsiq8WWHRaVFH49OA+a2ODgrC9sH/Q==} - dependencies: - axios: 1.6.2(debug@4.3.4) - transitivePeerDependencies: - - debug - dev: false - /lnbits@1.1.5(debug@4.3.4): + lnbits@1.1.5: resolution: {integrity: sha512-RPCBNsKKxlyQTHPKdU66iiXFBz6SuISVVkxJoSZY3Z+CBEzOu6xpgzZtQcZTbc1BCLqQc6HeK4qtfByKWjBTmg==} - dependencies: - axios: 0.21.4(debug@4.3.4) - typescript: 4.9.5 - transitivePeerDependencies: - - debug - dev: false - /load-tsconfig@0.2.5: + load-tsconfig@0.2.5: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - /locate-path@6.0.0: + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: false - /lodash.merge@4.6.2: + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: false - /lodash.sortby@4.7.0: + lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - dev: true - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: false - - /make-dir@3.1.0: + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} - dependencies: - semver: 6.3.0 - dev: false - /make-error@1.3.6: + make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - /media-typer@0.3.0: + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - dev: false - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: false + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} - /merge-stream@2.0.0: + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - /merge2@1.4.1: + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - dev: true - /methods@1.1.2: + methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - dev: false - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - /mime-db@1.52.0: + mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - dev: false - /mime-types@2.1.35: + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: false - /mime@1.6.0: + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} hasBin: true - dev: false - /mimic-fn@2.1.0: + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - dev: true - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} - /minimist@1.2.8: + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: false - /minipass@3.3.6: + minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - dev: false - /minipass@5.0.0: + minipass@5.0.0: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} - dev: false - /minizlib@2.1.2: + minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - dev: false - /mkdirp@1.0.4: + mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} hasBin: true - dev: false - /ms@2.0.0: + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: false - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - /ms@2.1.3: + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: false - /mute-stream@1.0.0: + mute-stream@1.0.0: resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: false - /mz@2.7.0: + mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - dev: true - /natural-compare@1.4.0: + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: false - /negotiator@0.6.3: + negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} - dev: false - /neo-async@2.6.2: + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: false - /next-tick@1.1.0: + next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - dev: false - /node-addon-api@5.1.0: + node-addon-api@5.1.0: resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} - dev: false - /node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - dev: false + node-exports-info@1.6.0: + resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==} + engines: {node: '>= 0.4'} - /node-fetch@2.7.0: + node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} peerDependencies: @@ -2661,235 +1881,173 @@ packages: peerDependenciesMeta: encoding: optional: true - dependencies: - whatwg-url: 5.0.0 - dev: false - /node-fetch@3.3.2: - resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - data-uri-to-buffer: 4.0.1 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - dev: false - - /node-gyp-build@4.6.0: - resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==} + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true - dev: false - /nopt@5.0.0: + nopt@5.0.0: resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} engines: {node: '>=6'} hasBin: true - dependencies: - abbrev: 1.1.1 - dev: false - /normalize-path@3.0.0: + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - dev: true - /nostr-tools@1.17.0(typescript@5.1.3): - resolution: {integrity: sha512-LZmR8GEWKZeElbFV5Xte75dOeE9EFUW/QLI1Ncn3JKn0kFddDKEfBbFN8Mu4TMs+L4HR/WTPha2l+PPuRnJcMw==} + nostr-tools@2.23.5: + resolution: {integrity: sha512-Fa7ZlUdjfUW1P4E7H3yBexhOHYi18XNyvd2n7eNHkYR085xADX6Y8V8Vm7nT/XQajaFOBrptXmVIGkJ2E4vfVw==} peerDependencies: typescript: '>=5.0.0' peerDependenciesMeta: typescript: optional: true - dependencies: - '@noble/ciphers': 0.2.0 - '@noble/curves': 1.1.0 - '@noble/hashes': 1.3.1 - '@scure/base': 1.1.1 - '@scure/bip32': 1.3.1 - '@scure/bip39': 1.2.1 - typescript: 5.1.3 - dev: false - /npm-run-path@4.0.1: + nostr-wasm@0.1.0: + resolution: {integrity: sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==} + + npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - /npmlog@5.0.1: + npmlog@5.0.1: resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - dev: false + deprecated: This package is no longer supported. - /object-assign@4.1.1: + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - /object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - dev: false + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} - /object-keys@1.1.1: + object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - dev: false - /object.assign@4.1.4: - resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: false - /object.values@1.1.6: - resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: false - /on-exit-leak-free@2.1.2: + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} - dev: false - /on-finished@2.4.1: + on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: false - /once@1.4.0: + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - /onetime@5.1.2: + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + oniguruma-parser@0.12.2: + resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==} + + oniguruma-to-es@4.3.6: + resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: false - /os-tmpdir@1.0.2: + os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} - dev: false - /p-limit@3.1.0: + outvariant@1.4.0: + resolution: {integrity: sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: false - /p-locate@5.0.0: + p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: false - /parent-module@1.0.1: + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: false - /parseurl@1.3.3: + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} - dev: false - /path-exists@4.0.0: + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - dev: false - /path-is-absolute@1.0.1: + path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - /path-key@3.1.1: + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - /path-parse@1.0.7: + path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: false - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: false + path-to-regexp@0.1.13: + resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==} - /path-type@4.0.0: + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} - dev: true - /pino-abstract-transport@1.1.0: - resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==} - dependencies: - readable-stream: 4.4.2 - split2: 4.2.0 - dev: false + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} - /pino-std-serializers@6.2.2: - resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} - dev: false + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} - /pino@8.16.2: - resolution: {integrity: sha512-2advCDGVEvkKu9TTVSa/kWW7Z3htI/sBKEZpqiHk6ive0i/7f5b1rsU8jn0aimxqfnSz5bj/nOYkwhBUn5xxvg==} + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + + pino@9.14.0: + resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==} hasBin: true - dependencies: - atomic-sleep: 1.0.0 - fast-redact: 3.3.0 - on-exit-leak-free: 2.1.2 - pino-abstract-transport: 1.1.0 - pino-std-serializers: 6.2.2 - process-warning: 2.3.1 - quick-format-unescaped: 4.0.4 - real-require: 0.2.0 - safe-stable-stringify: 2.4.3 - sonic-boom: 3.7.0 - thread-stream: 2.4.1 - dev: false - /pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} - dev: true - /postcss-load-config@4.0.1(ts-node@10.9.1): - resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} engines: {node: '>= 14'} peerDependencies: postcss: '>=8.0.9' @@ -2899,504 +2057,374 @@ packages: optional: true ts-node: optional: true - dependencies: - lilconfig: 2.1.0 - ts-node: 10.9.1(@types/node@18.16.18)(typescript@5.1.3) - yaml: 2.3.2 - dev: true - /prelude-ls@1.2.1: + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - dev: false - /prisma@5.4.1: - resolution: {integrity: sha512-op9PmU8Bcw5dNAas82wBYTG0yHnpq9/O3bhxbDBrNzwZTwBqsVCxxYRLf6wHNh9HVaDGhgjjHlu1+BcW8qdnBg==} + prisma@5.22.0: + resolution: {integrity: sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==} engines: {node: '>=16.13'} hasBin: true - requiresBuild: true - dependencies: - '@prisma/engines': 5.4.1 - /process-warning@2.3.1: - resolution: {integrity: sha512-JjBvFEn7MwFbzUDa2SRtKJSsyO0LlER4V/FmwLMhBlXNbGgGxdyFCxIdMDLerWUycsVUyaoM9QFLvppFy4IWaQ==} - dev: false + process-warning@3.0.0: + resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} - /process@0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - dev: false + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} - /proxy-addr@2.0.7: + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: false - /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: false + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} - /punycode@2.3.0: - resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} - engines: {node: '>=6'} - dev: true - - /punycode@2.3.1: + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - dev: false - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + qs@6.15.2: + resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.4 - dev: false - /queue-microtask@1.2.3: + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - /quick-format-unescaped@4.0.4: + quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} - dev: false - /range-parser@1.2.1: + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} - dev: false - /raw-body@2.5.1: - resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: false - /readable-stream@3.6.2: + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: false - /readable-stream@4.4.2: - resolution: {integrity: sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - abort-controller: 3.0.0 - buffer: 6.0.3 - events: 3.3.0 - process: 0.11.10 - string_decoder: 1.3.0 - dev: false - - /readdirp@3.6.0: + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - /real-require@0.2.0: + real-require@0.2.0: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} - dev: false - /regexp.prototype.flags@1.5.0: - resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - functions-have-names: 1.2.3 - dev: false - /require-directory@2.1.1: + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.1.0: + resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - dev: false - /require-from-string@2.0.2: + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - dev: false - /resolve-from@4.0.0: + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: false - /resolve-from@5.0.0: + resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} - dev: true - /resolve@1.22.2: - resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} + resolve@2.0.0-next.7: + resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==} + engines: {node: '>= 0.4'} hasBin: true - dependencies: - is-core-module: 2.12.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: false - /ret@0.2.2: - resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} - engines: {node: '>=4'} - dev: false + ret@0.4.3: + resolution: {integrity: sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==} + engines: {node: '>=10'} - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - /rfdc@1.3.0: - resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} - dev: false + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - /rimraf@3.0.2: + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - dependencies: - glob: 7.2.3 - dev: false - /rollup@3.29.3: - resolution: {integrity: sha512-T7du6Hum8jOkSWetjRgbwpM6Sy0nECYrYRSmZjayFcOddtKJWU4d17AC3HNUk7HRuqy4p+G7aEZclSHytqUmEg==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} + rollup@4.60.4: + resolution: {integrity: sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - optionalDependencies: - fsevents: 2.3.3 - dev: true - /run-async@3.0.0: + run-async@3.0.0: resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} engines: {node: '>=0.12.0'} - dev: false - /run-parallel@1.2.0: + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - /safe-buffer@5.2.1: + safe-array-concat@1.1.4: + resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: false - /safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - is-regex: 1.1.4 - dev: false + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} - /safe-regex2@2.0.0: - resolution: {integrity: sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==} - dependencies: - ret: 0.2.2 - dev: false + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} - /safe-stable-stringify@2.4.3: - resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} + safe-regex2@3.1.0: + resolution: {integrity: sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} engines: {node: '>=10'} - dev: false - /safer-buffer@2.1.2: + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: false - /secure-json-parse@2.7.0: + secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - dev: false - /semver@6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - dev: false - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + semver@7.8.1: + resolution: {integrity: sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==} engines: {node: '>=10'} hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: false - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: false - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - dev: false - /set-blocking@2.0.0: + set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: false - /set-cookie-parser@2.6.0: - resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} - dev: false + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} - /setprototypeof@1.2.0: + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: false - /shebang-command@2.0.0: + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - /shebang-regex@3.0.0: + shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - /side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - object-inspect: 1.12.3 - dev: false + shiki@3.23.0: + resolution: {integrity: sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==} - /signal-exit@3.0.7: + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - /slash@3.0.0: + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - dev: true - /sonic-boom@3.7.0: - resolution: {integrity: sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==} - dependencies: - atomic-sleep: 1.0.0 - dev: false + sonic-boom@4.2.1: + resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} - /source-map@0.6.1: + source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - dev: false - /source-map@0.8.0-beta.0: + source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} - dependencies: - whatwg-url: 7.1.0 - dev: true + deprecated: The work that was done in this beta branch won't be included in future versions - /split2@4.2.0: + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - dev: false - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + static-browser-server@1.0.3: + resolution: {integrity: sha512-ZUyfgGDdFRbZGGJQ1YhiM930Yczz5VlbJObrQLlk24+qNHVQx4OlLcYswEUo3bIyNAbQUIUR9Yr5/Hqjzqb4zA==} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} - dev: false - /string-width@4.2.3: + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + strict-event-emitter@0.4.6: + resolution: {integrity: sha512-12KWeb+wixJohmnwNFerbyiBrAlq5qJLwIt38etRtKtmmHyDSoGlIqFE9wx+4IwG0aDjI7GV8tc8ZccjWZZtTg==} + + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: false - /string.prototype.trim@1.2.7: - resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: false - /string.prototype.trimend@1.0.6: - resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: false + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} - /string.prototype.trimstart@1.0.6: - resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.21.2 - dev: false + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} - /string_decoder@1.3.0: + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: false - /strip-ansi@6.0.1: + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: false - /strip-bom@3.0.0: + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - dev: false - /strip-final-newline@2.0.0: + strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} - dev: true - /strip-json-comments@3.1.1: + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - dev: false - /sucrase@3.34.0: - resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} - engines: {node: '>=8'} + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + engines: {node: '>=16 || 14 >=14.17'} hasBin: true - dependencies: - '@jridgewell/gen-mapping': 0.3.3 - commander: 4.1.1 - glob: 7.1.6 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.6 - ts-interface-checker: 0.1.13 - dev: true - /supports-color@7.2.0: + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: false - /supports-preserve-symlinks-flag@1.0.0: + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - dev: false - /tar@6.2.0: - resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - dev: false + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: false - - /thenify-all@1.6.0: + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} - dependencies: - thenify: 3.3.1 - dev: true - /thenify@3.3.1: + thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - dependencies: - any-promise: 1.3.0 - dev: true - /thread-stream@2.4.1: - resolution: {integrity: sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==} - dependencies: - real-require: 0.2.0 - dev: false + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} - /tmp@0.0.33: + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: false - /to-regex-range@5.0.1: + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - /toad-cache@3.3.1: - resolution: {integrity: sha512-oE5vIpiyKEuyYJiyp0gYhiD1o7BmiPCJZX9pboK9X6EfdYYmNsk8m7J1kBwMt6H/avuDsCdEhassrMMxwW7h3Q==} - engines: {node: '>=12'} - dev: false + toad-cache@3.7.1: + resolution: {integrity: sha512-5DXWzE4Vz7xNHsv+xQ+MGfJYyC78Aok3tEr0MNwHoRf7vZnga1mQXZ4/Nsodld4VR6Wd+VhfmqnNrsRJyYPfrQ==} + engines: {node: '>=20'} - /toidentifier@1.0.1: + toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - dev: false - /tr46@0.0.3: + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: false - /tr46@1.0.1: + tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - dependencies: - punycode: 2.3.0 - dev: true - /tree-kill@1.2.2: + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - dev: true - /ts-interface-checker@0.1.13: + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - dev: true - /ts-node@10.9.1(@types/node@18.16.18)(typescript@5.1.3): - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true peerDependencies: '@swc/core': '>=1.2.50' @@ -3408,49 +2436,25 @@ packages: optional: true '@swc/wasm': optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 18.16.18 - acorn: 8.9.0 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.1.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - /tsconfig-paths@3.14.2: - resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - dev: false + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - /tseep@1.2.1: - resolution: {integrity: sha512-VFnsNcPGC4qFJ1nxbIPSjTmtRZOhlqLmtwRqtLVos8mbRHki8HO9cy9Z1e89EiWyxFmq6LBviI9TQjijxw/mEw==} - dev: false + tseep@1.3.1: + resolution: {integrity: sha512-ZPtfk1tQnZVyr7BPtbJ93qaAh2lZuIOpTMjhrYa4XctT8xe7t4SAW9LIxrySDuYMsfNNayE51E/WNGrNVgVicQ==} - /tstl@2.5.13: - resolution: {integrity: sha512-h9wayHHFI5+yqt8iau0vqH96cTNhezhZ/Fk/hrIdpfkiMu3lg9nzyvMfs5bIdX51IVzZO6DudLqhkL/rVXpT6g==} - dev: false + tstl@2.5.16: + resolution: {integrity: sha512-+O2ybLVLKcBwKm4HymCEwZIT0PpwS3gCYnxfSDEjJEKADvIFruaQjd3m7CAKNU1c7N3X3WjVz87re7TA2A5FUw==} - /tsup@7.2.0(ts-node@10.9.1)(typescript@5.1.3): - resolution: {integrity: sha512-vDHlczXbgUvY3rWvqFEbSqmC1L7woozbzngMqTtL2PGBODTtWlRwGDDawhvWzr5c1QjKe4OAKqJGfE1xeXUvtQ==} - engines: {node: '>=16.14'} + tsup@7.3.0: + resolution: {integrity: sha512-Ja1eaSRrE+QarmATlNO5fse2aOACYMBX+IZRKy1T+gpyH+jXgRrl5l4nHIQJQ1DoDgEjHDTw8cpE085UdBZuWQ==} + engines: {node: '>=18'} + deprecated: Breaking node 16 hasBin: true peerDependencies: '@swc/core': ^1 postcss: ^8.4.12 - typescript: '>=4.1.0' + typescript: '>=4.5.0' peerDependenciesMeta: '@swc/core': optional: true @@ -3458,261 +2462,178 @@ packages: optional: true typescript: optional: true - dependencies: - bundle-require: 4.0.2(esbuild@0.18.20) - cac: 6.7.14 - chokidar: 3.5.3 - debug: 4.3.4 - esbuild: 0.18.20 - execa: 5.1.1 - globby: 11.1.0 - joycon: 3.1.1 - postcss-load-config: 4.0.1(ts-node@10.9.1) - resolve-from: 5.0.0 - rollup: 3.29.3 - source-map: 0.8.0-beta.0 - sucrase: 3.34.0 - tree-kill: 1.2.2 - typescript: 5.1.3 - transitivePeerDependencies: - - supports-color - - ts-node - dev: true - /type-check@0.4.0: + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: false - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: false - - /type-fest@0.21.3: + type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - dev: false - /type-is@1.6.18: + type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - dev: false - /type@1.2.0: - resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} - dev: false + type@2.7.3: + resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} - /type@2.7.2: - resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} - dev: false + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} - /typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} - dependencies: - call-bind: 1.0.2 - for-each: 0.3.3 - is-typed-array: 1.1.10 - dev: false + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} - /typedarray-to-buffer@3.1.5: + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.8: + resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} + engines: {node: '>= 0.4'} + + typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - dependencies: - is-typedarray: 1.0.0 - dev: false - /typescript-lru-cache@2.0.0: + typescript-lru-cache@2.0.0: resolution: {integrity: sha512-Jp57Qyy8wXeMkdNuZiglE6v2Cypg13eDA1chHwDG6kq51X7gk4K7P7HaDdzZKCxkegXkVHNcPD0n5aW6OZH3aA==} - dev: false - /typescript@4.9.5: + typescript@4.9.5: resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} engines: {node: '>=4.2.0'} hasBin: true - dev: false - /typescript@5.1.3: - resolution: {integrity: sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} hasBin: true - requiresBuild: true - dev: false - optional: true - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.2 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: false + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} - /unpipe@1.0.0: + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - dev: false - /uri-js@4.4.1: + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: false - /utf-8-validate@5.0.10: + utf-8-validate@5.0.10: resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} engines: {node: '>=6.14.2'} - requiresBuild: true - dependencies: - node-gyp-build: 4.6.0 - dev: false - /utf8-buffer@1.0.0: - resolution: {integrity: sha512-ueuhzvWnp5JU5CiGSY4WdKbiN/PO2AZ/lpeLiz2l38qwdLy/cW40XobgyuIWucNyum0B33bVB0owjFCeGBSLqg==} - engines: {node: '>=8'} - dev: false - - /util-deprecate@1.0.2: + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: false - /utils-merge@1.0.1: + utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} - dev: false - /v8-compile-cache-lib@3.0.1: + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true - /vary@1.1.2: + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - dev: false - /web-streams-polyfill@3.3.3: - resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} - engines: {node: '>= 8'} - dev: false + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} - /webidl-conversions@3.0.1: + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: false - /webidl-conversions@4.0.2: + webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - dev: true - /websocket-polyfill@0.0.3: + websocket-polyfill@0.0.3: resolution: {integrity: sha512-pF3kR8Uaoau78MpUmFfzbIRxXj9PeQrCuPepGE6JIsfsJ/o/iXr07Q2iQNzKSSblQJ0FiGWlS64N4pVSm+O3Dg==} - dependencies: - tstl: 2.5.13 - websocket: 1.0.34 - transitivePeerDependencies: - - supports-color - dev: false - /websocket@1.0.34: - resolution: {integrity: sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==} + websocket@1.0.35: + resolution: {integrity: sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q==} engines: {node: '>=4.0.0'} - dependencies: - bufferutil: 4.0.7 - debug: 2.6.9 - es5-ext: 0.10.62 - typedarray-to-buffer: 3.1.5 - utf-8-validate: 5.0.10 - yaeti: 0.0.6 - transitivePeerDependencies: - - supports-color - dev: false - /whatwg-url@5.0.0: + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - dev: false - /whatwg-url@7.1.0: + whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - dependencies: - lodash.sortby: 4.7.0 - tr46: 1.0.1 - webidl-conversions: 4.0.2 - dev: true - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: false - - /which-typed-array@1.1.9: - resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - is-typed-array: 1.1.10 - dev: false - /which@2.0.2: + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.21: + resolution: {integrity: sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw==} + engines: {node: '>= 0.4'} + + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true - dependencies: - isexe: 2.0.0 - /wide-align@1.1.5: + wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - dependencies: - string-width: 4.2.3 - dev: false - /wordwrap@1.0.0: + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: false - /wrap-ansi@6.2.0: + wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: false - /wrap-ansi@7.0.0: + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: false - /wrappy@1.0.2: + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - /ws@8.13.0: - resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3722,51 +2643,2881 @@ packages: optional: true utf-8-validate: optional: true - dev: false - /y18n@5.0.8: + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} - dev: false - /yaeti@0.0.6: + yaeti@0.0.6: resolution: {integrity: sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==} engines: {node: '>=0.10.32'} - dev: false + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - /yallist@4.0.0: + yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: false - /yaml@2.3.2: - resolution: {integrity: sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==} - engines: {node: '>= 14'} - dev: true + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true - /yargs-parser@21.1.1: + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - dev: false - /yargs@17.7.2: + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@codesandbox/nodebox@0.1.8': + dependencies: + outvariant: 1.4.0 + strict-event-emitter: 0.4.6 + + '@codesandbox/sandpack-client@2.19.8': + dependencies: + '@codesandbox/nodebox': 0.1.8 + buffer: 6.0.3 + dequal: 2.0.3 + mime-db: 1.54.0 + outvariant: 1.4.0 + static-browser-server: 1.0.3 + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@esbuild/aix-ppc64@0.19.12': + optional: true + + '@esbuild/android-arm64@0.19.12': + optional: true + + '@esbuild/android-arm@0.19.12': + optional: true + + '@esbuild/android-x64@0.19.12': + optional: true + + '@esbuild/darwin-arm64@0.19.12': + optional: true + + '@esbuild/darwin-x64@0.19.12': + optional: true + + '@esbuild/freebsd-arm64@0.19.12': + optional: true + + '@esbuild/freebsd-x64@0.19.12': + optional: true + + '@esbuild/linux-arm64@0.19.12': + optional: true + + '@esbuild/linux-arm@0.19.12': + optional: true + + '@esbuild/linux-ia32@0.19.12': + optional: true + + '@esbuild/linux-loong64@0.19.12': + optional: true + + '@esbuild/linux-mips64el@0.19.12': + optional: true + + '@esbuild/linux-ppc64@0.19.12': + optional: true + + '@esbuild/linux-riscv64@0.19.12': + optional: true + + '@esbuild/linux-s390x@0.19.12': + optional: true + + '@esbuild/linux-x64@0.19.12': + optional: true + + '@esbuild/netbsd-x64@0.19.12': + optional: true + + '@esbuild/openbsd-x64@0.19.12': + optional: true + + '@esbuild/sunos-x64@0.19.12': + optional: true + + '@esbuild/win32-arm64@0.19.12': + optional: true + + '@esbuild/win32-ia32@0.19.12': + optional: true + + '@esbuild/win32-x64@0.19.12': + optional: true + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4)': + dependencies: + eslint: 9.39.4 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.2': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.5': + dependencies: + ajv: 6.15.0 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.4': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@fastify/ajv-compiler@3.6.0': + dependencies: + ajv: 8.20.0 + ajv-formats: 2.1.1(ajv@8.20.0) + fast-uri: 2.4.0 + + '@fastify/error@3.4.1': {} + + '@fastify/fast-json-stringify-compiler@4.3.0': + dependencies: + fast-json-stringify: 5.16.1 + + '@fastify/formbody@7.4.0': + dependencies: + fast-querystring: 1.1.2 + fastify-plugin: 4.5.1 + + '@fastify/merge-json-schemas@0.1.1': + dependencies: + fast-deep-equal: 3.1.3 + + '@fastify/view@8.2.0': + dependencies: + fastify-plugin: 4.5.1 + hashlru: 2.3.0 + + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@inquirer/checkbox@1.5.2': + dependencies: + '@inquirer/core': 6.0.0 + '@inquirer/type': 1.5.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + figures: 3.2.0 + + '@inquirer/confirm@1.0.11': + dependencies: + '@inquirer/core': 1.3.0 + '@inquirer/type': 1.5.5 + chalk: 4.1.2 + + '@inquirer/core@1.3.0': + dependencies: + '@inquirer/type': 1.5.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-spinners: 2.9.2 + cli-width: 4.1.0 + figures: 3.2.0 + mute-stream: 1.0.0 + run-async: 3.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + '@inquirer/core@6.0.0': + dependencies: + '@inquirer/type': 1.5.5 + '@types/mute-stream': 0.0.4 + '@types/node': 20.19.41 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-spinners: 2.9.2 + cli-width: 4.1.0 + figures: 3.2.0 + mute-stream: 1.0.0 + run-async: 3.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + '@inquirer/editor@1.2.15': + dependencies: + '@inquirer/core': 6.0.0 + '@inquirer/type': 1.5.5 + chalk: 4.1.2 + external-editor: 3.1.0 + + '@inquirer/expand@1.1.16': + dependencies: + '@inquirer/core': 6.0.0 + '@inquirer/type': 1.5.5 + chalk: 4.1.2 + figures: 3.2.0 + + '@inquirer/input@1.2.16': + dependencies: + '@inquirer/core': 6.0.0 + '@inquirer/type': 1.5.5 + chalk: 4.1.2 + + '@inquirer/password@1.1.16': + dependencies: + '@inquirer/core': 6.0.0 + '@inquirer/type': 1.5.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + + '@inquirer/prompts@1.2.3': + dependencies: + '@inquirer/checkbox': 1.5.2 + '@inquirer/confirm': 1.0.11 + '@inquirer/core': 1.3.0 + '@inquirer/editor': 1.2.15 + '@inquirer/expand': 1.1.16 + '@inquirer/input': 1.2.16 + '@inquirer/password': 1.1.16 + '@inquirer/rawlist': 1.2.16 + '@inquirer/select': 1.3.3 + + '@inquirer/rawlist@1.2.16': + dependencies: + '@inquirer/core': 6.0.0 + '@inquirer/type': 1.5.5 + chalk: 4.1.2 + + '@inquirer/select@1.3.3': + dependencies: + '@inquirer/core': 6.0.0 + '@inquirer/type': 1.5.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + figures: 3.2.0 + + '@inquirer/type@1.5.5': + dependencies: + mute-stream: 1.0.0 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@mapbox/node-pre-gyp@1.0.11': + dependencies: + detect-libc: 2.1.2 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.7.0 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.8.1 + tar: 6.2.1 + transitivePeerDependencies: + - encoding + - supports-color + + '@noble/ciphers@2.1.1': {} + + '@noble/curves@1.9.7': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/curves@2.0.1': + dependencies: + '@noble/hashes': 2.0.1 + + '@noble/hashes@1.8.0': {} + + '@noble/hashes@2.0.1': {} + + '@noble/secp256k1@2.3.0': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@nostr-dev-kit/ndk@3.0.3(nostr-tools@2.23.5(typescript@5.9.3))': + dependencies: + '@codesandbox/sandpack-client': 2.19.8 + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@noble/secp256k1': 2.3.0 + '@scure/base': 1.2.6 + debug: 4.4.3 + light-bolt11-decoder: 3.2.0 + nostr-tools: 2.23.5(typescript@5.9.3) + shiki: 3.23.0 + tseep: 1.3.1 + typescript-lru-cache: 2.0.0 + transitivePeerDependencies: + - supports-color + + '@open-draft/deferred-promise@2.2.0': {} + + '@pinojs/redact@0.4.0': {} + + '@prisma/client@5.22.0(prisma@5.22.0)': + optionalDependencies: + prisma: 5.22.0 + + '@prisma/debug@5.22.0': {} + + '@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2': {} + + '@prisma/engines@5.22.0': + dependencies: + '@prisma/debug': 5.22.0 + '@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 + '@prisma/fetch-engine': 5.22.0 + '@prisma/get-platform': 5.22.0 + + '@prisma/fetch-engine@5.22.0': + dependencies: + '@prisma/debug': 5.22.0 + '@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 + '@prisma/get-platform': 5.22.0 + + '@prisma/get-platform@5.22.0': + dependencies: + '@prisma/debug': 5.22.0 + + '@rollup/rollup-android-arm-eabi@4.60.4': + optional: true + + '@rollup/rollup-android-arm64@4.60.4': + optional: true + + '@rollup/rollup-darwin-arm64@4.60.4': + optional: true + + '@rollup/rollup-darwin-x64@4.60.4': + optional: true + + '@rollup/rollup-freebsd-arm64@4.60.4': + optional: true + + '@rollup/rollup-freebsd-x64@4.60.4': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.60.4': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.60.4': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.60.4': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.60.4': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.60.4': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.60.4': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.60.4': + optional: true + + '@rollup/rollup-linux-x64-musl@4.60.4': + optional: true + + '@rollup/rollup-openbsd-x64@4.60.4': + optional: true + + '@rollup/rollup-openharmony-arm64@4.60.4': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.60.4': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.60.4': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.60.4': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.60.4': + optional: true + + '@rtsao/scc@1.1.0': {} + + '@scure/base@1.1.1': {} + + '@scure/base@1.2.6': {} + + '@scure/base@2.0.0': {} + + '@scure/bip32@2.0.1': + dependencies: + '@noble/curves': 2.0.1 + '@noble/hashes': 2.0.1 + '@scure/base': 2.0.0 + + '@scure/bip39@2.0.1': + dependencies: + '@noble/hashes': 2.0.1 + '@scure/base': 2.0.0 + + '@shikijs/core@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.3.6 + + '@shikijs/engine-oniguruma@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/themes@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/types@3.23.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@10.0.2': {} + + '@tsconfig/node10@1.0.12': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + + '@types/estree@1.0.8': {} + + '@types/estree@1.0.9': {} + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/json-schema@7.0.15': {} + + '@types/json5@0.0.29': {} + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/ms@2.1.0': {} + + '@types/mute-stream@0.0.4': + dependencies: + '@types/node': 18.19.130 + + '@types/node@18.19.130': + dependencies: + undici-types: 5.26.5 + + '@types/node@20.19.41': + dependencies: + undici-types: 6.21.0 + + '@types/unist@3.0.3': {} + + '@types/wrap-ansi@3.0.0': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@ungap/structured-clone@1.3.1': {} + + abbrev@1.1.1: {} + + abstract-logging@2.0.1: {} + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn-walk@8.3.5: + dependencies: + acorn: 8.16.0 + + acorn@8.16.0: {} + + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + ajv-formats@2.1.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + aproba@2.1.0: {} + + are-we-there-yet@2.0.0: + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + + arg@4.1.3: {} + + argparse@2.0.1: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-flatten@1.1.1: {} + + array-includes@3.1.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + + array-union@2.1.0: {} + + array.prototype.findlastindex@1.2.6: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + async-function@1.0.0: {} + + asynckit@0.4.0: {} + + atomic-sleep@1.0.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + avvio@8.4.0: + dependencies: + '@fastify/error': 3.4.1 + fastq: 1.20.1 + + axios@0.21.4(debug@4.4.3): + dependencies: + follow-redirects: 1.16.0(debug@4.4.3) + transitivePeerDependencies: + - debug + + axios@1.16.1(debug@4.4.3): + dependencies: + follow-redirects: 1.16.0(debug@4.4.3) + form-data: 4.0.5 + https-proxy-agent: 5.0.1 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + - supports-color + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + bcrypt@5.1.1: + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + node-addon-api: 5.1.0 + transitivePeerDependencies: + - encoding + - supports-color + + binary-extensions@2.3.0: {} + + body-parser@1.20.5: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.15.2 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + brace-expansion@1.1.15: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bufferutil@4.1.0: + dependencies: + node-gyp-build: 4.8.4 + + bundle-require@4.2.1(esbuild@0.19.12): + dependencies: + esbuild: 0.19.12 + load-tsconfig: 0.2.5 + + bytes@3.1.2: {} + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + ccount@2.0.1: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + chardet@0.7.0: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chownr@2.0.0: {} + + cli-spinners@2.9.2: {} + + cli-width@4.1.0: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + color-support@1.1.3: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + comma-separated-tokens@2.0.3: {} + + commander@4.1.1: {} + + concat-map@0.0.1: {} + + console-control-strings@1.1.0: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-signature@1.0.7: {} + + cookie@0.7.2: {} + + create-require@1.1.1: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-js@4.2.0: {} + + d@1.0.2: + dependencies: + es5-ext: 0.10.64 + type: 2.7.3 + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + delayed-stream@1.0.0: {} + + delegates@1.0.0: {} + + depd@2.0.0: {} + + dequal@2.0.3: {} + + destroy@1.2.0: {} + + detect-libc@2.1.2: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diff@4.0.4: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + dotenv@16.6.1: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ee-first@1.1.1: {} + + emoji-regex@8.0.0: {} + + encodeurl@2.0.0: {} + + es-abstract@1.24.2: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.4 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.8 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.21 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.4 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + es5-ext@0.10.64: + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + esniff: 2.0.1 + next-tick: 1.1.0 + + es6-iterator@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-symbol: 3.1.4 + + es6-symbol@3.1.4: + dependencies: + d: 1.0.2 + ext: 1.7.0 + + esbuild@0.19.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-prettier@8.10.2(eslint@9.39.4): + dependencies: + eslint: 9.39.4 + + eslint-import-resolver-node@0.3.10: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.2 + resolve: 2.0.0-next.7 + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.13.0(eslint-import-resolver-node@0.3.10)(eslint@9.39.4): + dependencies: + debug: 3.2.7 + optionalDependencies: + eslint: 9.39.4 + eslint-import-resolver-node: 0.3.10 + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.32.0(eslint@9.39.4): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.39.4 + eslint-import-resolver-node: 0.3.10 + eslint-module-utils: 2.13.0(eslint-import-resolver-node@0.3.10)(eslint@9.39.4) + hasown: 2.0.4 + is-core-module: 2.16.2 + is-glob: 4.0.3 + minimatch: 3.1.5 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.39.4: + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.2 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.39.4 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + ajv: 6.15.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + esniff@2.0.1: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-emitter: 0.3.5 + type: 2.7.3 + + espree@10.4.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 4.2.1 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + event-emitter@0.3.5: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + + eventemitter3@5.0.4: {} + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + express@4.22.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.5 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.2 + fresh: 0.5.2 + http-errors: 2.0.1 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.13 + proxy-addr: 2.0.7 + qs: 6.15.2 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.2 + serve-static: 1.16.3 + setprototypeof: 1.2.0 + statuses: 2.0.2 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + ext@1.7.0: + dependencies: + type: 2.7.3 + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + + fast-content-type-parse@1.1.0: {} + + fast-decode-uri-component@1.0.1: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-json-stringify@5.16.1: + dependencies: + '@fastify/merge-json-schemas': 0.1.1 + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-deep-equal: 3.1.3 + fast-uri: 2.4.0 + json-schema-ref-resolver: 1.0.1 + rfdc: 1.4.1 + + fast-levenshtein@2.0.6: {} + + fast-querystring@1.1.2: + dependencies: + fast-decode-uri-component: 1.0.1 + + fast-uri@2.4.0: {} + + fast-uri@3.1.2: {} + + fastify-plugin@4.5.1: {} + + fastify@4.29.1: + dependencies: + '@fastify/ajv-compiler': 3.6.0 + '@fastify/error': 3.4.1 + '@fastify/fast-json-stringify-compiler': 4.3.0 + abstract-logging: 2.0.1 + avvio: 8.4.0 + fast-content-type-parse: 1.1.0 + fast-json-stringify: 5.16.1 + find-my-way: 8.2.2 + light-my-request: 5.14.0 + pino: 9.14.0 + process-warning: 3.0.0 + proxy-addr: 2.0.7 + rfdc: 1.4.1 + secure-json-parse: 2.7.0 + semver: 7.8.1 + toad-cache: 3.7.1 + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + figures@3.2.0: + dependencies: + escape-string-regexp: 1.0.5 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.3.2: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-my-way@8.2.2: + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 3.1.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.4.2 + keyv: 4.5.4 + + flatted@3.4.2: {} + + follow-redirects@1.16.0(debug@4.4.3): + optionalDependencies: + debug: 4.4.3 + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.4 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + gauge@3.0.2: + dependencies: + aproba: 2.1.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + + generator-function@2.0.1: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + get-stream@6.0.1: {} + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@14.0.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.2.0: {} + + handlebars@4.7.9: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + has-unicode@2.0.1: {} + + hashlru@2.3.0: {} + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + html-void-elements@3.0.0: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.4 + side-channel: 1.1.0 + + ipaddr.js@1.9.1: {} + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.2: + dependencies: + hasown: 2.0.4 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-stream@2.0.1: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.21 + + is-typedarray@1.0.0: {} + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isomorphic-ws@5.0.0(ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)): + dependencies: + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + + joycon@3.1.1: {} + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-ref-resolver@1.0.1: + dependencies: + fast-deep-equal: 3.1.3 + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + light-bolt11-decoder@3.2.0: + dependencies: + '@scure/base': 1.1.1 + + light-my-request@5.14.0: + dependencies: + cookie: 0.7.2 + process-warning: 3.0.0 + set-cookie-parser: 2.7.2 + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + lnbits-ts@0.0.2(debug@4.4.3): + dependencies: + axios: 1.16.1(debug@4.4.3) + transitivePeerDependencies: + - debug + - supports-color + + lnbits@1.1.5(debug@4.4.3): + dependencies: + axios: 0.21.4(debug@4.4.3) + typescript: 4.9.5 + transitivePeerDependencies: + - debug + + load-tsconfig@0.2.5: {} + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + lodash.sortby@4.7.0: {} + + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + + make-error@1.3.6: {} + + math-intrinsics@1.1.0: {} + + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.1 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + + media-typer@0.3.0: {} + + merge-descriptors@1.0.3: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + methods@1.1.2: {} + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-encode@2.0.1: {} + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + mimic-fn@2.1.0: {} + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.15 + + minimist@1.2.8: {} + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@5.0.0: {} + + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + + mkdirp@1.0.4: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + mute-stream@1.0.0: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + neo-async@2.6.2: {} + + next-tick@1.1.0: {} + + node-addon-api@5.1.0: {} + + node-exports-info@1.6.0: + dependencies: + array.prototype.flatmap: 1.3.3 + es-errors: 1.3.0 + object.entries: 1.1.9 + semver: 6.3.1 + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-gyp-build@4.8.4: {} + + nopt@5.0.0: + dependencies: + abbrev: 1.1.1 + + normalize-path@3.0.0: {} + + nostr-tools@2.23.5(typescript@5.9.3): + dependencies: + '@noble/ciphers': 2.1.1 + '@noble/curves': 2.0.1 + '@noble/hashes': 2.0.1 + '@scure/base': 2.0.0 + '@scure/bip32': 2.0.1 + '@scure/bip39': 2.0.1 + nostr-wasm: 0.1.0 + optionalDependencies: + typescript: 5.9.3 + + nostr-wasm@0.1.0: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + npmlog@5.0.1: + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + on-exit-leak-free@2.1.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + oniguruma-parser@0.12.2: {} + + oniguruma-to-es@4.3.6: + dependencies: + oniguruma-parser: 0.12.2 + regex: 6.1.0 + regex-recursion: 6.0.2 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + os-tmpdir@1.0.2: {} + + outvariant@1.4.0: {} + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parseurl@1.3.3: {} + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-to-regexp@0.1.13: {} + + path-type@4.0.0: {} + + picomatch@2.3.2: {} + + picomatch@4.0.4: {} + + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@7.1.0: {} + + pino@9.14.0: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.1 + thread-stream: 3.1.0 + + pirates@4.0.7: {} + + possible-typed-array-names@1.1.0: {} + + postcss-load-config@4.0.2(ts-node@10.9.2(@types/node@18.19.130)(typescript@5.9.3)): + dependencies: + lilconfig: 3.1.3 + yaml: 2.9.0 + optionalDependencies: + ts-node: 10.9.2(@types/node@18.19.130)(typescript@5.9.3) + + prelude-ls@1.2.1: {} + + prisma@5.22.0: + dependencies: + '@prisma/engines': 5.22.0 + optionalDependencies: + fsevents: 2.3.3 + + process-warning@3.0.0: {} + + process-warning@5.0.0: {} + + property-information@7.1.0: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-from-env@2.1.0: {} + + punycode@2.3.1: {} + + qs@6.15.2: + dependencies: + side-channel: 1.1.0 + + queue-microtask@1.2.3: {} + + quick-format-unescaped@4.0.4: {} + + range-parser@1.2.1: {} + + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.2 + + real-require@0.2.0: {} + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.1.0: + dependencies: + regex-utilities: 2.3.0 + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve@2.0.0-next.7: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.2 + node-exports-info: 1.6.0 + object-keys: 1.1.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + ret@0.4.3: {} + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rollup@4.60.4: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.60.4 + '@rollup/rollup-android-arm64': 4.60.4 + '@rollup/rollup-darwin-arm64': 4.60.4 + '@rollup/rollup-darwin-x64': 4.60.4 + '@rollup/rollup-freebsd-arm64': 4.60.4 + '@rollup/rollup-freebsd-x64': 4.60.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.4 + '@rollup/rollup-linux-arm-musleabihf': 4.60.4 + '@rollup/rollup-linux-arm64-gnu': 4.60.4 + '@rollup/rollup-linux-arm64-musl': 4.60.4 + '@rollup/rollup-linux-loong64-gnu': 4.60.4 + '@rollup/rollup-linux-loong64-musl': 4.60.4 + '@rollup/rollup-linux-ppc64-gnu': 4.60.4 + '@rollup/rollup-linux-ppc64-musl': 4.60.4 + '@rollup/rollup-linux-riscv64-gnu': 4.60.4 + '@rollup/rollup-linux-riscv64-musl': 4.60.4 + '@rollup/rollup-linux-s390x-gnu': 4.60.4 + '@rollup/rollup-linux-x64-gnu': 4.60.4 + '@rollup/rollup-linux-x64-musl': 4.60.4 + '@rollup/rollup-openbsd-x64': 4.60.4 + '@rollup/rollup-openharmony-arm64': 4.60.4 + '@rollup/rollup-win32-arm64-msvc': 4.60.4 + '@rollup/rollup-win32-ia32-msvc': 4.60.4 + '@rollup/rollup-win32-x64-gnu': 4.60.4 + '@rollup/rollup-win32-x64-msvc': 4.60.4 + fsevents: 2.3.3 + + run-async@3.0.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-array-concat@1.1.4: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safe-regex2@3.1.0: + dependencies: + ret: 0.4.3 + + safe-stable-stringify@2.5.0: {} + + safer-buffer@2.1.2: {} + + secure-json-parse@2.7.0: {} + + semver@6.3.1: {} + + semver@7.8.1: {} + + send@0.19.2: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.3: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2 + transitivePeerDependencies: + - supports-color + + set-blocking@2.0.0: {} + + set-cookie-parser@2.7.2: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shiki@3.23.0: + dependencies: + '@shikijs/core': 3.23.0 + '@shikijs/engine-javascript': 3.23.0 + '@shikijs/engine-oniguruma': 3.23.0 + '@shikijs/langs': 3.23.0 + '@shikijs/themes': 3.23.0 + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + slash@3.0.0: {} + + sonic-boom@4.2.1: + dependencies: + atomic-sleep: 1.0.0 + + source-map@0.6.1: {} + + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + + space-separated-tokens@2.0.2: {} + + split2@4.2.0: {} + + static-browser-server@1.0.3: + dependencies: + '@open-draft/deferred-promise': 2.2.0 + dotenv: 16.6.1 + mime-db: 1.54.0 + outvariant: 1.4.0 + + statuses@2.0.2: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + strict-event-emitter@0.4.6: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-bom@3.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-json-comments@3.1.1: {} + + sucrase@3.35.1: + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + commander: 4.1.1 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + tinyglobby: 0.2.17 + ts-interface-checker: 0.1.13 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toad-cache@3.7.1: {} + + toidentifier@1.0.1: {} + + tr46@0.0.3: {} + + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + + tree-kill@1.2.2: {} + + trim-lines@3.0.1: {} + + ts-interface-checker@0.1.13: {} + + ts-node@10.9.2(@types/node@18.19.130)(typescript@5.9.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.12 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 18.19.130 + acorn: 8.16.0 + acorn-walk: 8.3.5 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.4 + make-error: 1.3.6 + typescript: 5.9.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tseep@1.3.1: {} + + tstl@2.5.16: {} + + tsup@7.3.0(ts-node@10.9.2(@types/node@18.19.130)(typescript@5.9.3))(typescript@5.9.3): + dependencies: + bundle-require: 4.2.1(esbuild@0.19.12) + cac: 6.7.14 + chokidar: 3.6.0 + debug: 4.4.3 + esbuild: 0.19.12 + execa: 5.1.1 + globby: 11.1.0 + joycon: 3.1.1 + postcss-load-config: 4.0.2(ts-node@10.9.2(@types/node@18.19.130)(typescript@5.9.3)) + resolve-from: 5.0.0 + rollup: 4.60.4 + source-map: 0.8.0-beta.0 + sucrase: 3.35.1 + tree-kill: 1.2.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + - ts-node + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.21.3: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + type@2.7.3: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.8: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typedarray-to-buffer@3.1.5: + dependencies: + is-typedarray: 1.0.0 + + typescript-lru-cache@2.0.0: {} + + typescript@4.9.5: {} + + typescript@5.9.3: {} + + uglify-js@3.19.3: + optional: true + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + undici-types@5.26.5: {} + + undici-types@6.21.0: {} + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + unpipe@1.0.0: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + utf-8-validate@5.0.10: + dependencies: + node-gyp-build: 4.8.4 + + util-deprecate@1.0.2: {} + + utils-merge@1.0.1: {} + + v8-compile-cache-lib@3.0.1: {} + + vary@1.1.2: {} + + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + + webidl-conversions@3.0.1: {} + + webidl-conversions@4.0.2: {} + + websocket-polyfill@0.0.3: + dependencies: + tstl: 2.5.16 + websocket: 1.0.35 + transitivePeerDependencies: + - supports-color + + websocket@1.0.35: + dependencies: + bufferutil: 4.1.0 + debug: 2.6.9 + es5-ext: 0.10.64 + typedarray-to-buffer: 3.1.5 + utf-8-validate: 5.0.10 + yaeti: 0.0.6 + transitivePeerDependencies: + - supports-color + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.21 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.21: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wide-align@1.1.5: + dependencies: + string-width: 4.2.3 + + word-wrap@1.2.5: {} + + wordwrap@1.0.0: {} + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): + optionalDependencies: + bufferutil: 4.1.0 + utf-8-validate: 5.0.10 + + y18n@5.0.8: {} + + yaeti@0.0.6: {} + + yallist@4.0.0: {} + + yaml@2.9.0: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: dependencies: cliui: 8.0.1 - escalade: 3.1.1 + escalade: 3.2.0 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: false - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true + yn@3.1.1: {} - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: false + yocto-queue@0.1.0: {} + + zwitch@2.0.4: {} From 94b5d553764428bda4a7f50350fbfd1838879cbb Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 31 May 2026 12:14:29 +0200 Subject: [PATCH 19/36] refactor: adapt source to NDK 3.0.3 / nostr-tools v2 surface (#14) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mechanical adjustments to the source after the dep bump in the previous commit. No semantic changes — every site adapts to API drift between the pinned versions. Surface changes addressed: * `NDKKind` strict numeric enum (was wider in 2.8.1). 18 sites passed the literal `24134` (NIP-46 admin-RPC response kind) to `rpc.sendResponse` / `rpc.sendRequest`; NDK 3's `NDKKind` enum omits 24134. Introduced `src/daemon/admin/kinds.ts` exporting `NIP46_ADMIN_RESPONSE_KIND = 24134 as NDKKind` so the cast lives once, and routed all 18 sites through the named constant. * `NDKPrivateKeySigner` constructor now accepts nsec1 or hex directly (the `@ai-guardrail` in NDK 3 source explicitly tells callers not to `nip19.decode` ahead of construction). Simplified `Daemon.startKey` and `createNewKey` accordingly — the bech32 decode workaround for #8 was tied to NDK 2.8.1's old behavior and is no longer needed. * `NDKPrivateKeySigner.privateKey` is `string` (hex) on the public surface, not `Uint8Array`. `nostr-tools` v2's `nip19.nsecEncode` wants `Uint8Array`. Replaced `nip19.nsecEncode(key.privateKey!)` with `key.nsec` (NDK 3 exposes the getter directly), avoiding both the type mismatch and the unnecessary round-trip. For the one remaining hex-string-from-config call site, used `nostrUtils.hexToBytes` to convert before encoding. * `NDKPool` event rename: `'relay:notice'` → `'notice'`, with flipped arg order `(notice, relay)` → `(relay, notice)`. * `NDKUser.fromNip05` now requires the `ndk` instance as a 2nd positional arg (was implicit-global before). * `Nip46PermitCallbackParams.params` narrowed to `string | NostrEvent`; type guards added at the two access sites (`authorize.ts` and `acl/index.ts:requestToSigningConditionQuery`). * `req.params` is now `(string | undefined)[]` instead of `any[]`; `create_account.ts` `authorizationWithPayload` branch now explicitly throws on missing username/domain before passing to `createAccountReal` (validates what was implicit before). * Removed `src/daemon/backend/publish-event.ts` (defined a strategy that's never registered — wiring is commented out in `backend/index.ts:22`; in NDK 3 the file refs the removed `NDKNip46Backend.signEvent`). Dead since at least NDK 2.x; the bump just made the breakage visible. Pre-existing `tsc` errors at `src/db.ts` and `src/daemon/authorize.ts` on `'PrismaClient'` / `'Request'` exports are unrelated to this PR — the regtest container's nix derivation can't reach the prisma engine binary store on this host (`nsecbunkerd#14` parked separately). `pnpm run build` (tsup) is green; the Docker container runs `prisma generate` against its own engine at image-build time and resolves these at runtime. #11's wire-name policy convention adoption is the next commit — this one is purely keep-it-compiling work. Refs aiolabs/nsecbunkerd#14. --- src/client.ts | 2 +- src/daemon/admin/commands/add_policy_rule.ts | 3 +- .../admin/commands/add_signing_condition.ts | 3 +- src/daemon/admin/commands/create_account.ts | 5 ++- src/daemon/admin/commands/create_new_key.ts | 10 +++-- .../admin/commands/create_new_policy.ts | 3 +- src/daemon/admin/commands/create_new_token.ts | 3 +- src/daemon/admin/commands/ping.ts | 3 +- .../admin/commands/remove_policy_rule.ts | 3 +- .../commands/remove_signing_condition.ts | 3 +- src/daemon/admin/commands/rename_key_user.ts | 3 +- src/daemon/admin/commands/revoke_token.ts | 3 +- src/daemon/admin/commands/revoke_user.ts | 3 +- src/daemon/admin/commands/unlock_key.ts | 3 +- src/daemon/admin/commands/update_policy.ts | 3 +- src/daemon/admin/index.ts | 15 +++---- src/daemon/admin/kinds.ts | 14 +++++++ src/daemon/authorize.ts | 5 +-- src/daemon/backend/index.ts | 2 - src/daemon/backend/publish-event.ts | 14 ------- src/daemon/lib/acl/index.ts | 8 +++- src/daemon/run.ts | 40 +++++++------------ 22 files changed, 79 insertions(+), 72 deletions(-) create mode 100644 src/daemon/admin/kinds.ts delete mode 100644 src/daemon/backend/publish-event.ts diff --git a/src/client.ts b/src/client.ts index 0fcad60..89b1c0d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -100,7 +100,7 @@ function loadPrivateKey(): string | undefined { } else { // check if we have a @ so we try to get the npub from nip05 if (remotePubkey.includes('@')) { - const u = await NDKUser.fromNip05(remotePubkey); + const u = await NDKUser.fromNip05(remotePubkey, ndk); if (!u) { console.log(`Invalid nip05 ${remotePubkey}`); process.exit(1); diff --git a/src/daemon/admin/commands/add_policy_rule.ts b/src/daemon/admin/commands/add_policy_rule.ts index 041fd1e..7a66345 100644 --- a/src/daemon/admin/commands/add_policy_rule.ts +++ b/src/daemon/admin/commands/add_policy_rule.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import prisma from "../../../db.js"; /** @@ -43,5 +44,5 @@ export default async function addPolicyRule(admin: AdminInterface, req: NDKRpcRe }); const result = JSON.stringify(["ok"]); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } diff --git a/src/daemon/admin/commands/add_signing_condition.ts b/src/daemon/admin/commands/add_signing_condition.ts index 6cfad88..f734d24 100644 --- a/src/daemon/admin/commands/add_signing_condition.ts +++ b/src/daemon/admin/commands/add_signing_condition.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import prisma from "../../../db.js"; /** @@ -42,5 +43,5 @@ export default async function addSigningCondition(admin: AdminInterface, req: ND }); const result = JSON.stringify(["ok"]); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } diff --git a/src/daemon/admin/commands/create_account.ts b/src/daemon/admin/commands/create_account.ts index f3c026a..2919d9c 100644 --- a/src/daemon/admin/commands/create_account.ts +++ b/src/daemon/admin/commands/create_account.ts @@ -131,6 +131,9 @@ export default async function createAccount(admin: AdminInterface, req: NDKRpcRe username = payload[0]; domain = payload[1]; email = payload[2]; + if (!username || !domain) { + throw new Error('Invalid authorization payload: missing username/domain'); + } return createAccountReal(admin, req, username, domain, email); } } @@ -195,7 +198,7 @@ export async function createAccountReal( } const keyName = nip05; - const nsec = nip19.nsecEncode(key.privateKey!); + const nsec = key.nsec; currentConfig.keys[keyName] = { key: key.privateKey }; saveCurrentConfig(admin.configFile, currentConfig); diff --git a/src/daemon/admin/commands/create_new_key.ts b/src/daemon/admin/commands/create_new_key.ts index 306962c..468c3cf 100644 --- a/src/daemon/admin/commands/create_new_key.ts +++ b/src/daemon/admin/commands/create_new_key.ts @@ -1,7 +1,7 @@ import NDK, { NDKEvent, NDKPrivateKeySigner, NDKRpcRequest, type NostrEvent } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import { saveEncrypted } from "../../../commands/add.js"; -import { nip19 } from 'nostr-tools'; import { setupSkeletonProfile } from "../../lib/profile.js"; export default async function createNewKey(admin: AdminInterface, req: NDKRpcRequest) { @@ -13,7 +13,9 @@ export default async function createNewKey(admin: AdminInterface, req: NDKRpcReq let key; if (_nsec) { - key = new NDKPrivateKeySigner(nip19.decode(_nsec).data as string); + // NDK 3.x's `NDKPrivateKeySigner` accepts nsec1 or hex directly + // (see core/src/signers/private-key/index.ts `@ai-guardrail`). + key = new NDKPrivateKeySigner(_nsec); } else { key = NDKPrivateKeySigner.generate(); @@ -23,7 +25,7 @@ export default async function createNewKey(admin: AdminInterface, req: NDKRpcReq } const user = await key.user(); - const nsec = nip19.nsecEncode(key.privateKey!); + const nsec = key.nsec; await saveEncrypted( admin.configFile, @@ -38,5 +40,5 @@ export default async function createNewKey(admin: AdminInterface, req: NDKRpcReq npub: user.npub, }); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } diff --git a/src/daemon/admin/commands/create_new_policy.ts b/src/daemon/admin/commands/create_new_policy.ts index e924c43..0a6a787 100644 --- a/src/daemon/admin/commands/create_new_policy.ts +++ b/src/daemon/admin/commands/create_new_policy.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import prisma from "../../../db.js"; export default async function createNewPolicy(admin: AdminInterface, req: NDKRpcRequest) { @@ -29,5 +30,5 @@ export default async function createNewPolicy(admin: AdminInterface, req: NDKRpc } const result = JSON.stringify(["ok"]); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } \ No newline at end of file diff --git a/src/daemon/admin/commands/create_new_token.ts b/src/daemon/admin/commands/create_new_token.ts index 04588c4..b66765f 100644 --- a/src/daemon/admin/commands/create_new_token.ts +++ b/src/daemon/admin/commands/create_new_token.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import prisma from "../../../db.js"; export default async function createNewToken(admin: AdminInterface, req: NDKRpcRequest) { @@ -30,5 +31,5 @@ export default async function createNewToken(admin: AdminInterface, req: NDKRpcR if (!tokenRecord) throw new Error("Token not created"); const result = JSON.stringify(["ok"]); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } \ No newline at end of file diff --git a/src/daemon/admin/commands/ping.ts b/src/daemon/admin/commands/ping.ts index ba63d7c..9368c44 100644 --- a/src/daemon/admin/commands/ping.ts +++ b/src/daemon/admin/commands/ping.ts @@ -1,6 +1,7 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; export default async function ping(admin: AdminInterface, req: NDKRpcRequest) { - return admin.rpc.sendResponse(req.id, req.pubkey, "ok", 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, "ok", NIP46_ADMIN_RESPONSE_KIND); } diff --git a/src/daemon/admin/commands/remove_policy_rule.ts b/src/daemon/admin/commands/remove_policy_rule.ts index b983acd..f8b7c60 100644 --- a/src/daemon/admin/commands/remove_policy_rule.ts +++ b/src/daemon/admin/commands/remove_policy_rule.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import prisma from "../../../db.js"; /** @@ -29,5 +30,5 @@ export default async function removePolicyRule(admin: AdminInterface, req: NDKRp await prisma.policyRule.delete({ where: { id: ruleId } }); const result = JSON.stringify(["ok"]); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } diff --git a/src/daemon/admin/commands/remove_signing_condition.ts b/src/daemon/admin/commands/remove_signing_condition.ts index 65eff96..0e4da78 100644 --- a/src/daemon/admin/commands/remove_signing_condition.ts +++ b/src/daemon/admin/commands/remove_signing_condition.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import prisma from "../../../db.js"; /** @@ -22,5 +23,5 @@ export default async function removeSigningCondition(admin: AdminInterface, req: await prisma.signingCondition.delete({ where: { id: conditionId } }); const result = JSON.stringify(["ok"]); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } diff --git a/src/daemon/admin/commands/rename_key_user.ts b/src/daemon/admin/commands/rename_key_user.ts index f2c4ab3..0877cf4 100644 --- a/src/daemon/admin/commands/rename_key_user.ts +++ b/src/daemon/admin/commands/rename_key_user.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import prisma from "../../../db.js"; export default async function renameKeyUser(admin: AdminInterface, req: NDKRpcRequest) { @@ -25,5 +26,5 @@ export default async function renameKeyUser(admin: AdminInterface, req: NDKRpcRe }); const result = JSON.stringify(["ok"]); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } diff --git a/src/daemon/admin/commands/revoke_token.ts b/src/daemon/admin/commands/revoke_token.ts index 1224d0a..db04c21 100644 --- a/src/daemon/admin/commands/revoke_token.ts +++ b/src/daemon/admin/commands/revoke_token.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import prisma from "../../../db.js"; /** @@ -32,5 +33,5 @@ export default async function revokeToken(admin: AdminInterface, req: NDKRpcRequ }); const result = JSON.stringify(["ok"]); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } diff --git a/src/daemon/admin/commands/revoke_user.ts b/src/daemon/admin/commands/revoke_user.ts index 409015e..9deb5b6 100644 --- a/src/daemon/admin/commands/revoke_user.ts +++ b/src/daemon/admin/commands/revoke_user.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import prisma from "../../../db.js"; export default async function revokeUser(admin: AdminInterface, req: NDKRpcRequest) { @@ -20,5 +21,5 @@ export default async function revokeUser(admin: AdminInterface, req: NDKRpcReque }); const result = JSON.stringify(["ok"]); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } diff --git a/src/daemon/admin/commands/unlock_key.ts b/src/daemon/admin/commands/unlock_key.ts index 03c8cbd..dc27f39 100644 --- a/src/daemon/admin/commands/unlock_key.ts +++ b/src/daemon/admin/commands/unlock_key.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; export default async function unlockKey(admin: AdminInterface, req: NDKRpcRequest) { const [ keyName, passphrase ] = req.params as [ string, string ]; @@ -16,5 +17,5 @@ export default async function unlockKey(admin: AdminInterface, req: NDKRpcReques result = JSON.stringify({ success: false, error: e.message }); } - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } \ No newline at end of file diff --git a/src/daemon/admin/commands/update_policy.ts b/src/daemon/admin/commands/update_policy.ts index 43028e5..ebc9805 100644 --- a/src/daemon/admin/commands/update_policy.ts +++ b/src/daemon/admin/commands/update_policy.ts @@ -1,5 +1,6 @@ import { NDKRpcRequest } from "@nostr-dev-kit/ndk"; import AdminInterface from "../index.js"; +import { NIP46_ADMIN_RESPONSE_KIND } from "../kinds.js"; import prisma from "../../../db.js"; /** @@ -39,5 +40,5 @@ export default async function updatePolicy(admin: AdminInterface, req: NDKRpcReq await prisma.policy.update({ where: { id: policyId }, data }); const result = JSON.stringify(["ok"]); - return admin.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return admin.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } diff --git a/src/daemon/admin/index.ts b/src/daemon/admin/index.ts index 21e5f23..e4d8509 100644 --- a/src/daemon/admin/index.ts +++ b/src/daemon/admin/index.ts @@ -19,6 +19,7 @@ import updatePolicy from './commands/update_policy'; import addSigningCondition from './commands/add_signing_condition'; import removeSigningCondition from './commands/remove_signing_condition'; import revokeToken from './commands/revoke_token'; +import { NIP46_ADMIN_RESPONSE_KIND } from './kinds.js'; import fs from 'fs'; import { validateRequestFromAdmin } from './validations/request-from-admin'; import { dmUser } from '../../utils/dm-user'; @@ -142,7 +143,7 @@ class AdminInterface { this.ndk.connect(2500).then(() => { // connect for whitelisted admins this.rpc.subscribe({ - "kinds": [NDKKind.NostrConnect, 24134 as number], + "kinds": [NDKKind.NostrConnect, NIP46_ADMIN_RESPONSE_KIND], "#p": [this.signerUser!.pubkey] }); @@ -272,7 +273,7 @@ class AdminInterface { const key = keys.find((k) => k.name === keyName); if (!key || !key.npub) { - return this.rpc.sendResponse(req.id, req.pubkey, JSON.stringify([]), 24134); + return this.rpc.sendResponse(req.id, req.pubkey, JSON.stringify([]), NIP46_ADMIN_RESPONSE_KIND); } const npub = key.npub; @@ -294,7 +295,7 @@ class AdminInterface { }; })); - return this.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return this.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } /** @@ -326,7 +327,7 @@ class AdminInterface { }; })); - return this.rpc.sendResponse(req.id, req.pubkey, result, 24134); + return this.rpc.sendResponse(req.id, req.pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } /** @@ -338,7 +339,7 @@ class AdminInterface { const result = JSON.stringify(await this.getKeys()); const pubkey = req.pubkey; - return this.rpc.sendResponse(req.id, pubkey, result, 24134); // 24134 + return this.rpc.sendResponse(req.id, pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } /** @@ -350,7 +351,7 @@ class AdminInterface { const result = JSON.stringify(await this.getKeyUsers(req)); const pubkey = req.pubkey; - return this.rpc.sendResponse(req.id, pubkey, result, 24134); // 24134 + return this.rpc.sendResponse(req.id, pubkey, result, NIP46_ADMIN_RESPONSE_KIND); } /** @@ -416,7 +417,7 @@ class AdminInterface { remoteUser.pubkey, 'acl', [params], - 24134, + NIP46_ADMIN_RESPONSE_KIND, (res: NDKRpcResponse) => { this.requestPermissionResponse( remotePubkey, diff --git a/src/daemon/admin/kinds.ts b/src/daemon/admin/kinds.ts new file mode 100644 index 0000000..85ba137 --- /dev/null +++ b/src/daemon/admin/kinds.ts @@ -0,0 +1,14 @@ +import type { NDKKind } from '@nostr-dev-kit/ndk'; + +/** + * NIP-46 admin-RPC response channel — kind-24134. Distinct from the + * standard NIP-46 client channel kind-24133 (`NDKKind.NostrConnect`) + * which carries `sign_event` / `nip04_*` / `nip44_*` / etc. + * + * nsecbunkerd's admin surface uses a dedicated kind so signer clients + * and admin clients don't subscribe to each other's events. + * + * NDK 3.x's `NDKKind` enum does not include 24134; the cast happens + * once here so callers can pass a typed value to `rpc.sendResponse`. + */ +export const NIP46_ADMIN_RESPONSE_KIND = 24134 as NDKKind; diff --git a/src/daemon/authorize.ts b/src/daemon/authorize.ts index cb9721b..2b17744 100644 --- a/src/daemon/authorize.ts +++ b/src/daemon/authorize.ts @@ -59,9 +59,8 @@ async function createRecord( ) { let params: string | undefined; - if (param?.rawEvent) { - const e = param as NDKEvent; - params = JSON.stringify(e.rawEvent()); + if (typeof param === 'object' && param !== null && 'rawEvent' in param) { + params = JSON.stringify(param.rawEvent()); } else if (param) { params = param.toString(); } diff --git a/src/daemon/backend/index.ts b/src/daemon/backend/index.ts index 861f10f..49112fc 100644 --- a/src/daemon/backend/index.ts +++ b/src/daemon/backend/index.ts @@ -18,8 +18,6 @@ export class Backend extends NDKNip46Backend { this.baseUrl = baseUrl; this.fastify = fastify; - - // this.setStrategy('publish_event', new PublishEventHandlingStrategy()); } /** diff --git a/src/daemon/backend/publish-event.ts b/src/daemon/backend/publish-event.ts deleted file mode 100644 index 3302523..0000000 --- a/src/daemon/backend/publish-event.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { NDKNip46Backend } from "@nostr-dev-kit/ndk"; -import { IEventHandlingStrategy } from '@nostr-dev-kit/ndk'; - -export default class PublishEventHandlingStrategy implements IEventHandlingStrategy { - async handle(backend: NDKNip46Backend, id: string, remotePubkey: string, params: string[]): Promise { - const event = await backend.signEvent(remotePubkey, params); - if (!event) return undefined; - - console.log('Publishing event', event); - await event.publish(); - - return JSON.stringify(await event.toNostrEvent()); - } -} diff --git a/src/daemon/lib/acl/index.ts b/src/daemon/lib/acl/index.ts index b32f954..2e3559a 100644 --- a/src/daemon/lib/acl/index.ts +++ b/src/daemon/lib/acl/index.ts @@ -124,9 +124,13 @@ export function requestToSigningConditionQuery(method: IMethod, payload?: string const signingConditionQuery: any = { method }; switch (method) { - case 'sign_event': - signingConditionQuery.kind = { in: [ payload?.kind?.toString(), 'all' ] }; + case 'sign_event': { + const kindString = (typeof payload === 'object' && payload?.kind !== undefined) + ? payload.kind.toString() + : undefined; + signingConditionQuery.kind = { in: [kindString, 'all'] }; break; + } } return signingConditionQuery; diff --git a/src/daemon/run.ts b/src/daemon/run.ts index 89eda0a..f664712 100644 --- a/src/daemon/run.ts +++ b/src/daemon/run.ts @@ -1,5 +1,5 @@ import NDK, { NDKPrivateKeySigner, Nip46PermitCallback, Nip46PermitCallbackParams } from '@nostr-dev-kit/ndk'; -import { nip19 } from 'nostr-tools'; +import { nip19, utils as nostrUtils } from 'nostr-tools'; import { Backend } from './backend/index.js'; import { IMethod, @@ -38,8 +38,7 @@ function getKeys(config: DaemonConfig) { const keys: Key[] = []; for (const [name, nsec] of Object.entries(config.keys)) { - const hexpk = nip19.decode(nsec).data as string; - const user = await new NDKPrivateKeySigner(hexpk).user(); + const user = await new NDKPrivateKeySigner(nsec).user(); const key = { name, npub: user.npub, @@ -164,7 +163,7 @@ class Daemon { explicitRelayUrls: config.nostr.relays, }); this.ndk.pool.on('relay:connect', (r) => console.log(`✅ Connected to ${r.url}`) ); - this.ndk.pool.on('relay:notice', (n, r) => { console.log(`👀 Notice from ${r.url}`, n); }); + this.ndk.pool.on('notice', (r, n) => { console.log(`👀 Notice from ${r.url}`, n); }); this.ndk.pool.on('relay:disconnect', (r) => { console.log(`🚫 Disconnected from ${r.url}`); @@ -206,7 +205,10 @@ class Daemon { continue; } - const nsec = nip19.nsecEncode(settings.key); + // nostr-tools v2: `nsecEncode` takes `Uint8Array`, not hex string. + // pragma: allowlist secret + // `settings.key` is the hex-encoded private key from config. + const nsec = nip19.nsecEncode(nostrUtils.hexToBytes(settings.key)); this.loadNsec(keyName, nsec); } } @@ -226,27 +228,13 @@ class Daemon { */ async startKey(name: string, nsec: string) { const cb = signingAuthorizationCallback(name, this.adminInterface); - let hexpk: string; - - if (nsec.startsWith('nsec1')) { - try { - // NDK 2.8.1's NDKPrivateKeySigner constructor passes its - // arg straight to nostr-tools getPublicKey() which requires - // 32-byte hex / bytes / bigint, not bech32. Without this - // decode, every key created via create_new_key fails to - // load with the nostr-tools getPublicKey type error, so - // the bunker can never sign for any target it provisions. - // See aiolabs/nsecbunkerd#8. - hexpk = nip19.decode(nsec).data as string; - } catch(e) { - console.error(`Error loading key ${name}:`, e); - return - } - } else { - hexpk = nsec; - } - - const backend = new Backend(this.ndk, this.fastify, hexpk, cb, this.config.baseUrl); + // NDK 3.x's `NDKPrivateKeySigner` accepts nsec1 or hex directly + // (see `core/src/signers/private-key/index.ts` `@ai-guardrail` + // — "DO NOT use nip19.decode() to convert nsec to hex before + // passing it here"). The bech32-decode workaround for #8 was + // tied to NDK 2.8.1's old constructor behavior and is no + // longer needed post-#14 NDK bump. + const backend = new Backend(this.ndk, this.fastify, nsec, cb, this.config.baseUrl); await backend.start(); } From db1a8345870dd543cf6c3c9bdf47f7dc5b5641e1 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 31 May 2026 12:15:57 +0200 Subject: [PATCH 20/36] refactor(acl): align IMethod with NIP-46 wire-name vocabulary (#14) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NDK 3.x's `NDKNip46Backend` passes the wire method name verbatim to `pubkeyAllowed` — `nip04_encrypt`, `nip04_decrypt`, `nip44_encrypt`, `nip44_decrypt`, etc. NDK 2.8.1 normalized these to `encrypt`/`decrypt` before calling the permit callback; that normalization was the root of why our encrypt/decrypt path had never worked end-to-end against lnbits's bunker-backed signer (lnbits stores `PolicyRule.method` using wire names, our auth lookup looked for the normalized name → no match → request fell through to the never-resolved admin prompt and timed out at 15s). Source `IMethod` directly from NDK's exported `NIP46Method` union so it can't drift across future bumps. If NDK adds a new method (e.g. `nip60_*`) we pick it up for free. Drop the `method as IMethod` cast at the `signingAuthorizationCallback` call site — both sides now share the same vocabulary by construction. This is the substantive win that aiolabs/nsecbunkerd#14 is filed for. With this commit: - `sign_event` policy rules with kinds continue to match exactly as before (kind stringification path unchanged). - `nip04_encrypt` / `nip04_decrypt` / `nip44_encrypt` / `nip44_decrypt` policy rules — kind-less — now match the live-policy join (step 4 of `checkIfPubkeyAllowed`) by their method-name alone. lnbits's bunker-mediated `signer.nip44_decrypt` and `signer.nip44_encrypt` calls (per `aiolabs/lnbits` PR #38 phase 2.4) start succeeding end-to-end against any operator account whose Policy carries those rules — which `_ensure_policy`'s self-heal already ensures for every newly-bound operator (per coord log 2026-05-30T22:00Z). - `switch_relays` (new in NDK 3) flows through the auth check the same way as any other method. `requestToSigningConditionQuery` needs no further change — the existing `sign_event` switch case covers the only method that discriminates on kind; all other methods use the default `{ method }` query against the override layer, which is correct for the kind-less wire names too. Refs aiolabs/nsecbunkerd#14, aiolabs/nsecbunkerd#11 (whose live-policy join this finally puts to use). --- src/daemon/lib/acl/index.ts | 23 +++++++++++++++++++++-- src/daemon/run.ts | 7 ++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/daemon/lib/acl/index.ts b/src/daemon/lib/acl/index.ts index 2e3559a..f621c98 100644 --- a/src/daemon/lib/acl/index.ts +++ b/src/daemon/lib/acl/index.ts @@ -1,4 +1,4 @@ -import { NDKEvent, NostrEvent } from '@nostr-dev-kit/ndk'; +import { NDKEvent, NostrEvent, NIP46Method } from '@nostr-dev-kit/ndk'; import prisma from '../../../db.js'; /** @@ -114,7 +114,26 @@ export async function checkIfPubkeyAllowed( return undefined; } -export type IMethod = "connect" | "sign_event" | "encrypt" | "decrypt" | "ping"; +/** + * Sign-time auth method names follow the NIP-46 wire convention as + * NDK 3.x's `NDKNip46Backend` passes them through to `pubkeyAllowed` + * verbatim (it stopped normalizing `nip04_encrypt`/`nip04_decrypt` + * to `encrypt`/`decrypt` somewhere between 2.8.1 and current + * upstream). + * + * lnbits's `_ensure_policy` writes `PolicyRule.method` using the same + * wire-name vocabulary (`nip04_encrypt`, `nip04_decrypt`, + * `nip44_encrypt`, `nip44_decrypt`, `sign_event`, `get_public_key`, + * `connect`, `ping`). With the wire-name vocabulary on both sides, + * the post-#11 live-policy join (step 4 of `checkIfPubkeyAllowed`) + * naturally matches lnbits's stored rules — no `encrypt → nip04_encrypt` + * adapter layer needed. + * + * Source the type from NDK itself so it can't drift across future + * NDK bumps; if NDK adds a new method (e.g. `nip60_*`) we pick it up + * for free. + */ +export type IMethod = NIP46Method; export type IAllowScope = { kind?: number | 'all'; diff --git a/src/daemon/run.ts b/src/daemon/run.ts index f664712..9497677 100644 --- a/src/daemon/run.ts +++ b/src/daemon/run.ts @@ -1,10 +1,7 @@ import NDK, { NDKPrivateKeySigner, Nip46PermitCallback, Nip46PermitCallbackParams } from '@nostr-dev-kit/ndk'; import { nip19, utils as nostrUtils } from 'nostr-tools'; import { Backend } from './backend/index.js'; -import { - IMethod, - checkIfPubkeyAllowed, -} from './lib/acl/index.js'; +import { checkIfPubkeyAllowed } from './lib/acl/index.js'; import AdminInterface from './admin/index.js'; import { IConfig } from '../config/index.js'; import { NDKRpcRequest } from '@nostr-dev-kit/ndk'; @@ -107,7 +104,7 @@ function signingAuthorizationCallback(keyName: string, adminInterface: AdminInte } try { - const keyAllowed = await checkIfPubkeyAllowed(keyName, remotePubkey, method as IMethod, payload); + const keyAllowed = await checkIfPubkeyAllowed(keyName, remotePubkey, method, payload); if (keyAllowed === true || keyAllowed === false) { console.log(`🔎 ${nip19.npubEncode(remotePubkey)} is ${keyAllowed ? 'allowed' : 'denied'} to ${method} with key ${keyName}`); From e8f245c91717cab51ab1cc248b02e65294270c02 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 31 May 2026 13:43:37 +0200 Subject: [PATCH 21/36] fix(deps): cap nostr-tools at ~2.20.0 (regtest Node 20 / curves v2 ESM-only) (#14) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Caught during regtest dogfood after the previous three commits landed. With `nostr-tools: ^2.17.2` pnpm resolved to 2.23.5, which in turn pulls `@noble/curves@2.0.1` — ESM-only. The regtest Dockerfile runs on Node 20.11.1, where CJS `require()` of pure-ESM modules is hard-blocked: Error [ERR_REQUIRE_ESM]: require() of ES Module /app/node_modules/.pnpm/@noble+curves@2.0.1/.../secp256k1.js from /app/node_modules/.pnpm/nostr-tools@2.23.5/.../index.js not supported. nostr-tools 2.21.0 was the cutover — that release flipped `@noble/curves` from `1.2.0` to `2.0.1`. 2.20.0 is the last nostr-tools 2.x release that's still CJS-friendly via @noble/curves 1.2.0. Capping our pin at `~2.20.0` keeps us within the "nostr-tools >= 2.17.2" range NDK 3.0.3 asks for in its peerDependency while sidestepping the ESM/CJS hazard. This isn't a regression we introduce — it's a CJS-output footgun unique to the regtest container's Node 20 + tsup-default-CJS combination. Long-term fix paths (out of scope here): * Bump the container's Node base image to >= 22 (where `--experimental-require-module` is on by default for `.js` files inside `package.json type: "commonjs"`) * Switch tsup output to ESM (`tsup --format esm`) — wider surface change across the daemon, the client CLI, and the Dockerfile entrypoint * Accept the cap forever (small downside: 2.21+ patch fixes won't reach us until we fix one of the above) The cap is intentionally tight (`~2.20.0` allows 2.20.x patches, nothing newer) so a future `pnpm update` doesn't silently jump us back over the 2.21 edge. Revisit when one of the long-term paths above lands. Refs aiolabs/nsecbunkerd#14, regtest dogfood 2026-05-31. --- package.json | 2 +- pnpm-lock.yaml | 98 ++++++++++++++++++++++++++------------------------ 2 files changed, 53 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index 2a6a4aa..b51595d 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "isomorphic-ws": "^5.0.0", "lnbits": "^1.1.5", "lnbits-ts": "^0.0.2", - "nostr-tools": "^2.17.2", + "nostr-tools": "~2.20.0", "websocket-polyfill": "^0.0.3", "ws": "^8.13.0", "yargs": "^17.7.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f550604..13e81b0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,7 +22,7 @@ importers: version: 1.2.3 '@nostr-dev-kit/ndk': specifier: 3.0.3 - version: 3.0.3(nostr-tools@2.23.5(typescript@5.9.3)) + version: 3.0.3(nostr-tools@2.20.0(typescript@5.9.3)) '@prisma/client': specifier: ^5.4.1 version: 5.22.0(prisma@5.22.0) @@ -75,8 +75,8 @@ importers: specifier: ^0.0.2 version: 0.0.2(debug@4.4.3) nostr-tools: - specifier: ^2.17.2 - version: 2.23.5(typescript@5.9.3) + specifier: ~2.20.0 + version: 2.20.0(typescript@5.9.3) websocket-polyfill: specifier: ^0.0.3 version: 0.0.3 @@ -400,26 +400,31 @@ packages: resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true - '@noble/ciphers@2.1.1': - resolution: {integrity: sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw==} - engines: {node: '>= 20.19.0'} + '@noble/ciphers@0.5.3': + resolution: {integrity: sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w==} + + '@noble/curves@1.1.0': + resolution: {integrity: sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==} + + '@noble/curves@1.2.0': + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} '@noble/curves@1.9.7': resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} engines: {node: ^14.21.3 || >=16} - '@noble/curves@2.0.1': - resolution: {integrity: sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==} - engines: {node: '>= 20.19.0'} + '@noble/hashes@1.3.1': + resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} + engines: {node: '>= 16'} + + '@noble/hashes@1.3.2': + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} '@noble/hashes@1.8.0': resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} engines: {node: ^14.21.3 || >=16} - '@noble/hashes@2.0.1': - resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==} - engines: {node: '>= 20.19.0'} - '@noble/secp256k1@2.3.0': resolution: {integrity: sha512-0TQed2gcBbIrh7Ccyw+y/uZQvbJwm7Ao4scBUxqpBCcsOlZG0O4KGfjtNAy/li4W8n1xt3dxrwJ0beZ2h2G6Kw==} @@ -618,14 +623,11 @@ packages: '@scure/base@1.2.6': resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} - '@scure/base@2.0.0': - resolution: {integrity: sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w==} + '@scure/bip32@1.3.1': + resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==} - '@scure/bip32@2.0.1': - resolution: {integrity: sha512-4Md1NI5BzoVP+bhyJaY3K6yMesEFzNS1sE/cP+9nuvE7p/b0kx9XbpDHHFl8dHtufcbdHRUUQdRqLIPHN/s7yA==} - - '@scure/bip39@2.0.1': - resolution: {integrity: sha512-PsxdFj/d2AcJcZDX1FXN3dDgitDDTmwf78rKZq1a6c1P1Nan1X/Sxc7667zU3U+AN60g7SxxP0YCVw2H/hBycg==} + '@scure/bip39@1.2.1': + resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} '@shikijs/core@3.23.0': resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==} @@ -1895,8 +1897,8 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - nostr-tools@2.23.5: - resolution: {integrity: sha512-Fa7ZlUdjfUW1P4E7H3yBexhOHYi18XNyvd2n7eNHkYR085xADX6Y8V8Vm7nT/XQajaFOBrptXmVIGkJ2E4vfVw==} + nostr-tools@2.20.0: + resolution: {integrity: sha512-Kq/2lMyeOdGvpDsYH2an8HP4H0aFCqwKythhTzxfgZTVv4L3NOgrJw2SxH8jkWlH8xPhWxGfN6lFtC+EAa2qYQ==} peerDependencies: typescript: '>=5.0.0' peerDependenciesMeta: @@ -2993,20 +2995,26 @@ snapshots: - encoding - supports-color - '@noble/ciphers@2.1.1': {} + '@noble/ciphers@0.5.3': {} + + '@noble/curves@1.1.0': + dependencies: + '@noble/hashes': 1.3.1 + + '@noble/curves@1.2.0': + dependencies: + '@noble/hashes': 1.3.2 '@noble/curves@1.9.7': dependencies: '@noble/hashes': 1.8.0 - '@noble/curves@2.0.1': - dependencies: - '@noble/hashes': 2.0.1 + '@noble/hashes@1.3.1': {} + + '@noble/hashes@1.3.2': {} '@noble/hashes@1.8.0': {} - '@noble/hashes@2.0.1': {} - '@noble/secp256k1@2.3.0': {} '@nodelib/fs.scandir@2.1.5': @@ -3021,7 +3029,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@nostr-dev-kit/ndk@3.0.3(nostr-tools@2.23.5(typescript@5.9.3))': + '@nostr-dev-kit/ndk@3.0.3(nostr-tools@2.20.0(typescript@5.9.3))': dependencies: '@codesandbox/sandpack-client': 2.19.8 '@noble/curves': 1.9.7 @@ -3030,7 +3038,7 @@ snapshots: '@scure/base': 1.2.6 debug: 4.4.3 light-bolt11-decoder: 3.2.0 - nostr-tools: 2.23.5(typescript@5.9.3) + nostr-tools: 2.20.0(typescript@5.9.3) shiki: 3.23.0 tseep: 1.3.1 typescript-lru-cache: 2.0.0 @@ -3147,18 +3155,16 @@ snapshots: '@scure/base@1.2.6': {} - '@scure/base@2.0.0': {} - - '@scure/bip32@2.0.1': + '@scure/bip32@1.3.1': dependencies: - '@noble/curves': 2.0.1 - '@noble/hashes': 2.0.1 - '@scure/base': 2.0.0 + '@noble/curves': 1.1.0 + '@noble/hashes': 1.3.1 + '@scure/base': 1.1.1 - '@scure/bip39@2.0.1': + '@scure/bip39@1.2.1': dependencies: - '@noble/hashes': 2.0.1 - '@scure/base': 2.0.0 + '@noble/hashes': 1.3.1 + '@scure/base': 1.1.1 '@shikijs/core@3.23.0': dependencies: @@ -4619,14 +4625,14 @@ snapshots: normalize-path@3.0.0: {} - nostr-tools@2.23.5(typescript@5.9.3): + nostr-tools@2.20.0(typescript@5.9.3): dependencies: - '@noble/ciphers': 2.1.1 - '@noble/curves': 2.0.1 - '@noble/hashes': 2.0.1 - '@scure/base': 2.0.0 - '@scure/bip32': 2.0.1 - '@scure/bip39': 2.0.1 + '@noble/ciphers': 0.5.3 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.1 + '@scure/base': 1.1.1 + '@scure/bip32': 1.3.1 + '@scure/bip39': 1.2.1 nostr-wasm: 0.1.0 optionalDependencies: typescript: 5.9.3 From b6f8abdb2373d9b5e22037eba513a9595491522f Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 31 May 2026 15:29:07 +0200 Subject: [PATCH 22/36] fix(daemon): make unlockKey idempotent (#16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `unlockKey(keyName, passphrase)` previously had no short-circuit on re-entry — calling it against an already-unlocked key would happily run through the full path: 1. decryptNsec (cheap, same result) 2. overwrite this.activeKeys[keyName] with the same nsec 3. call startKey(keyName, nsec) → spawn a SECOND Backend instance Step 3 is the actual hazard. Each Backend opens its own NIP-46 kind- 24133 subscription with the relay, scoped to the key's pubkey. Two Backends → duplicate subscription → wire events delivered twice and each handler races to publish its response. Response amplification + ordering hazards downstream, plus a slow leak of NDK subscription state every time unlock fires. This bug was latent under the manual-unlock posture today (admins rarely re-issue unlock_key for the same name in one session) but becomes load-bearing for #16's autounlock loop, which is designed to run alongside the existing startKeys() loops and may legitimately encounter a key that was already loaded via the unencrypted-config path. Belt-and-suspenders lnbits-side scripts + future periodic "re-unlock sweeps for paranoia" can also fire this. Fix: short-circuit on `this.activeKeys[keyName]` already set. Return true so callers can rely on "after this call returns, the key is unlocked and ready" regardless of whether work was done. Doesn't break the manual flow (still unlocks first-time), doesn't change the failure path (corrupt blob / wrong passphrase still throws), just closes the re-entry foot-gun. Refs aiolabs/nsecbunkerd#16 (autounlock — this is the idempotency sub-task lnbits flagged in the design surface). --- src/daemon/run.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/daemon/run.ts b/src/daemon/run.ts index 9497677..f91dbd7 100644 --- a/src/daemon/run.ts +++ b/src/daemon/run.ts @@ -236,6 +236,19 @@ class Daemon { } async unlockKey(keyName: string, passphrase: string): Promise { + // Idempotency guard: if a Backend instance already exists for this + // keyName, the key is already unlocked and the relay subscription + // for its kind-24133 channel is already active. Calling startKey + // again would spawn a SECOND Backend with a duplicate subscription + // — wire events would be handled twice, with race/amplification + // hazards on the response side. Return success without re-running + // startKey so callers (admin `unlock_key` RPC, autounlock loop, + // belt-and-suspenders fallback paths) can fire safely against + // already-unlocked keys. + if (this.activeKeys[keyName]) { + return true; + } + const keyData = this.config.allKeys[keyName]; const { iv, data } = keyData; From 7a3cb4f3da5d113180d88212b50888ce4de81da3 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 31 May 2026 15:31:25 +0200 Subject: [PATCH 23/36] feat(daemon): boot-time autounlock of encrypted keys (#16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds opt-in autounlock to the daemon's boot sequence. Closes the "O(N) manual unlock_key RPC per bunker restart" paper-cut without breaking the secure-by-default posture: deployments that want every restart to gate crypto capability on a human action keep that property by leaving both env vars unset. Configuration — two mutually exclusive env vars: NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE literal passphrase NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE_FILE path (newline-trimmed) Both set → fail loud at boot. Neither set → no-op (default, behavior unchanged from pre-#16). Var names follow the bunker's existing NSEC_BUNKER_* convention (see NSEC_BUNKER_DEBUG_TRANSPORT, NSEC_BUNKER_DISABLE_WATCHDOG); the design issue spec'd NSECBUNKER_* but aligning with the existing prefix matters more for operator muscle-memory than matching the issue text verbatim. Implementation: - `Daemon.maybeAutounlock()` wedged at the tail of `startKeys()`. Inherits the relay-subscription lifecycle (EOSE-awaited per #9) that the existing per-key startKey calls established, so there's no "client sees key locked" race window. - Enumeration via `prisma.key.findMany({ where: { deletedAt: null } })` — Key table is the canonical source of truth for what keys exist on the bunker; respects soft-delete. - Per-key call to the existing `unlockKey(keyName, passphrase)`, which is idempotent post-#16 — encrypted-at-rest keys get unlocked on first call; rows already loaded via the unencrypted-config passes above are no-ops. - Sequential loop with continue-on-error. One bad row (corrupted blob, key encrypted under a historical passphrase, etc.) doesn't block the rest of the fleet. Per-key INFO/WARN/ERROR + one summary line. - File-source error (missing path, permission denied) is fatal at boot — same severity as a misconfig. Observability output: 🔓 autounlock: unlocked (success) ⚠️ autounlock: unlockKey returned false for (...) (soft fail) ❌ autounlock: failed: (throw) 🔓 autounlock: enabled (source=), unlocked N/M keys in (summary) Single-passphrase invariant: every `create_new_key(name, passphrase)` in our usage today uses the same passphrase (LNBITS_NSEC_BUNKER_KEYSTORE_PASSPHRASE on the lnbits side), so one autounlock passphrase covers every encrypted key. Per-key passphrase support is a separate feature (out of scope — see #16 "out of scope" section + docs/AUTOUNLOCK.md "What's not in scope"). `docs/AUTOUNLOCK.md` ships alongside: usage, the security trade spelled out by deployment shape, observability hooks, what's deliberately not in scope. Required-reading link before any operator flips the env var on for a production-shaped deployment. Refs aiolabs/nsecbunkerd#16. Builds on idempotent unlockKey from the previous commit on this branch. --- docs/AUTOUNLOCK.md | 140 +++++++++++++++++++++++++++++++++++++++++++++ src/daemon/run.ts | 97 +++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 docs/AUTOUNLOCK.md diff --git a/docs/AUTOUNLOCK.md b/docs/AUTOUNLOCK.md new file mode 100644 index 0000000..6e0bd1b --- /dev/null +++ b/docs/AUTOUNLOCK.md @@ -0,0 +1,140 @@ +# Boot-time autounlock + +`nsecbunkerd` stores each managed key encrypted at rest in +`nsecbunker.db`. By default, every key is **locked** after the daemon +starts — clients must drive an `unlock_key` admin RPC against the +bunker before signing / encrypting / decrypting works for that key. + +Autounlock is an opt-in feature that, when enabled, reads a +passphrase from a configured source at boot and unlocks every +non-soft-deleted key in the `Key` table automatically. This trades +operational simplicity for a documented security weakening; read +this whole document before enabling. + +## Configuration + +Two mutually-exclusive environment variables: + +| Var | Meaning | +|---|---| +| `NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE` | Literal passphrase string. Useful for dev / `docker compose .env` flows. | +| `NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE_FILE` | Path to a file containing the passphrase (newline-trimmed at read). Idiomatic for sops / systemd-LoadCredential / k8s-secret / external secrets-manager flows where the passphrase comes from a separate credential store. | + +**If both are set, the daemon fails loud at boot** with an explicit +error. Ambiguous config is never allowed to silently pick one. + +**If neither is set, autounlock is off** — behavior is identical to +pre-#16: keys remain locked until an admin `unlock_key` RPC fires per +key per restart. + +## What happens at boot when autounlock is on + +After the daemon's existing key-loading passes complete (unencrypted +keys from in-process config, plain-key entries in `nsecbunker.json`), +the autounlock pass runs: + +1. Read the passphrase from the configured source. Failure to read + (missing file, no permission) is fatal at boot. +2. Enumerate every row in the `Key` Prisma table where + `deletedAt IS NULL`. +3. For each row, call `unlockKey(keyName, passphrase)`. `unlockKey` + is idempotent post-#16: if the key was already unlocked by a + prior pass, it's a no-op. +4. Log per-key INFO on success, WARN on `unlockKey → false` + (typically: wrong passphrase, possibly the key was created under a + historical passphrase that differs from the current one), ERROR on + throw (typically: corrupted blob). +5. Log one summary line: + `🔓 autounlock: enabled (source=), unlocked N/M keys in `. + +The loop is sequential — log clarity > parallelism, the unlock op +itself is cheap (one ChaCha20 decrypt per key). For 100 keys it's +milliseconds. If a fleet ever needs the thousands, parallelize then. + +The NIP-46 client channel doesn't accept RPCs that route to a key +until that key's `Backend.start()` resolves — which happens inside +`unlockKey`. So there's no race window where a freshly-restarted +bunker would say "key locked" to a client while the loop is in +flight on that key. + +## The security trade-off + +Enabling autounlock means **whoever can read the passphrase source +can recover any key from the bunker disk.** Specifically: + +- The encrypt-at-rest property of `nsecbunker.db` is *preserved* + against `cat /var/lib/nsecbunker/*.db` alone — the database holds + ciphertext + IV per key, not plaintext. +- The encrypt-at-rest property is *lost* if the attacker also has + access to the passphrase source. Anyone with read access to the + passphrase env var, the passphrase file, or the process memory at + the moment of autounlock can decrypt every key. + +This is the same trade today's deployments already make when they +hold the passphrase in `lnbits`'s env to drive `unlock_key` RPCs +post-restart. Autounlock makes the trade *explicit at the bunker +level* and *visible per-deployment*, but it doesn't introduce a new +trust requirement that didn't already exist for any deployment using +external automation to drive unlocks. + +### Recommendations by deployment shape + +- **Dev / regtest / single-host:** literal `NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE` + in `docker compose .env` is fine. The threat model on a dev box + doesn't justify the file-source ceremony. +- **Single-tenant production:** passphrase file on a separate + volume / mount with stricter access. Mount via + `systemd-LoadCredential` so the file is only readable by the + bunker process and is materialized from a sops-decrypted source + at boot. Avoid baking the passphrase into the container image or + process env list (which leaks into `ps aux`, container labels, etc.). +- **Multi-tenant / high-security:** leave autounlock off. Orchestrate + unlock per-restart from an external process that prompts for the + passphrase out-of-band (hardware token, HSM-derived secret, human + approval). This preserves the property that bunker startup alone + doesn't restore crypto capability — a deliberate human action is + required. + +## What's *not* in scope + +These are deliberately out of scope for the autounlock feature. +Separate issues to file if needed: + +- **Per-key passphrase support.** The current `Key` table doesn't + carry per-key passphrase metadata; every `create_new_key(name, passphrase)` + in our usage today uses the same passphrase + (`LNBITS_NSEC_BUNKER_KEYSTORE_PASSPHRASE`). The autounlock + passphrase covers every encrypted key by virtue of this + single-passphrase invariant. If a deployment ever needs per-key + passphrases, that's a separate feature (per-key passphrase-selector + column + per-key passphrase map). +- **Passphrase rotation.** Re-encrypting every key under a new + passphrase belongs in a dedicated admin RPC (`rotate_keystore`), + not in autounlock. +- **HSM / hardware-derived passphrase delivery.** Orthogonal to + where the passphrase comes from at unlock time — autounlock just + reads a string. An HSM integration would land between the + hardware and the file the bunker reads from. + +## Observability hooks + +The autounlock pass emits: + +- `🔓 autounlock: unlocked ` (INFO, one per success) +- `⚠️ autounlock: unlockKey returned false for ...` (WARN, one per soft failure) +- `❌ autounlock: failed: ` (ERROR, one per throw) +- `🔓 autounlock: enabled (source=), unlocked N/M keys in ` (summary, once) + +When the optional Prometheus exporter lands, counters +`nsecbunkerd_keys_unlocked_total` and `nsecbunkerd_keys_locked_total` +will be reported from the autounlock summary state. The current +implementation doesn't export metrics — the log line is the +canonical signal. + +## See also + +- `src/daemon/run.ts:Daemon.maybeAutounlock` — implementation +- `src/daemon/run.ts:Daemon.unlockKey` — the idempotent per-key call +- `src/daemon/admin/commands/unlock_key.ts` — the admin-RPC wrapper for manual unlock +- aiolabs/nsecbunkerd#16 — issue with full design rationale + acceptance criteria +- aiolabs/nsecbunkerd#15 — NDK 3.0.3 bump (the structural fix this builds on) diff --git a/src/daemon/run.ts b/src/daemon/run.ts index f91dbd7..7945867 100644 --- a/src/daemon/run.ts +++ b/src/daemon/run.ts @@ -208,6 +208,103 @@ class Daemon { const nsec = nip19.nsecEncode(nostrUtils.hexToBytes(settings.key)); this.loadNsec(keyName, nsec); } + + // Boot-time autounlock of encrypted-at-rest keys. Off by default; + // enabled by setting NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE or + // NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE_FILE. See docs/AUTOUNLOCK.md + // for the security trade-off and aiolabs/nsecbunkerd#16 for the + // design rationale. + await this.maybeAutounlock(); + } + + /** + * Boot-time autounlock for encrypted keys. + * + * Reads a passphrase from one of two mutually exclusive env vars: + * - NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE — literal passphrase + * - NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE_FILE — path to a file containing + * the passphrase (newline-trimmed) + * + * If neither is set, this is a no-op — the deployment opted out and + * keys remain locked until an admin `unlock_key` RPC fires per key + * per restart (today's default). + * + * If both are set, throws at boot — ambiguous config. + * + * Otherwise: enumerates `Key` table rows where `deletedAt IS NULL`, + * calls `unlockKey(keyName, passphrase)` per row. Sequential, with + * continue-on-error so one bad row doesn't block the rest of the + * fleet. Per-key INFO/WARN/ERROR log + one summary line at the end. + * + * `unlockKey` is idempotent post-#16 — calling it against a key that + * was already loaded via the unencrypted paths above is safe (returns + * true without spawning a duplicate Backend). + * + * Single-passphrase invariant: every `create_new_key(name, passphrase)` + * uses the same passphrase in our usage today, so one autounlock + * passphrase covers every encrypted key. Per-key passphrase support + * is a separate feature (out of scope — see issue #16). + */ + async maybeAutounlock(): Promise { + const literal = process.env.NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE; + const filePath = process.env.NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE_FILE; + + if (literal && filePath) { + throw new Error( + 'Autounlock: NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE and ' + + 'NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE_FILE are mutually exclusive. ' + + 'Set exactly one (or neither, to leave autounlock off).' + ); + } + + if (!literal && !filePath) { + return; // autounlock off (default) + } + + let passphrase: string; + let source: string; + if (literal) { + passphrase = literal; + source = 'NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE'; + } else { + const fs = await import('fs'); + try { + passphrase = fs.readFileSync(filePath!, 'utf8').replace(/\r?\n$/, ''); + } catch (e: any) { + throw new Error( + `Autounlock: failed to read passphrase file ${filePath}: ${e.message}` + ); + } + source = `NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE_FILE=${filePath}`; + } + + const keys = await prisma.key.findMany({ where: { deletedAt: null } }); + const start = Date.now(); + let success = 0; + + for (const key of keys) { + try { + const ok = await this.unlockKey(key.keyName, passphrase); + if (ok) { + console.log(`🔓 autounlock: unlocked ${key.keyName}`); + success++; + } else { + console.warn( + `⚠️ autounlock: unlockKey returned false for ${key.keyName} ` + + `(likely wrong passphrase — encrypted under a different secret?)` + ); + } + } catch (e: any) { + console.error( + `❌ autounlock: ${key.keyName} failed: ${e?.message ?? e}` + ); + } + } + + const elapsed = Date.now() - start; + console.log( + `🔓 autounlock: enabled (source=${source}), unlocked ${success}/${keys.length} keys in ${elapsed}ms` + ); } async start() { From 030d3cea0fa4f3904e52bdac01d1e934e87d9632 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 31 May 2026 15:34:51 +0200 Subject: [PATCH 24/36] fix(daemon): autounlock walks config.allKeys, not prisma.key (#16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first cut of `maybeAutounlock` enumerated `prisma.key` based on the design issue's pseudocode. Empirically that's the wrong source: the Prisma `Key` table is only populated by the NIP-05 `create_account` path, which stores keys *plain-at-rest* in `nsecbunker.json` (no encryption involved). The `create_new_key` flow that lnbits's `RemoteBunkerSigner` uses provisions encrypted `{iv, data}` blobs directly into the JSON `keys` map without touching the Prisma table at all. Result of the v1 enumeration on regtest: 🔓 autounlock: enabled (source=NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE), unlocked 0/0 keys in 0ms …despite 67 encrypted blobs sitting in nsecbunker.json. The Prisma table was empty because none of the regtest keys came from `create_account`. Greg's key would have been a no-op even with the autounlock env set; the manual `unlock_key` admin RPC would still have been required. Fix: enumerate `this.config.allKeys` (the in-memory snapshot of `nsecbunker.json`'s `keys` map, populated at daemon-fork time per `src/commands/start.ts:144`) filtered to entries with the `iv`+`data` shape. That's the canonical "what's encrypted at rest" set — exactly the rows for which manual `unlock_key` was previously required per restart. Plain-key entries (`{key: ...}` from `create_account`) are skipped here for log clarity — they were already loaded by `startKeys`' second pass and live in `activeKeys`; `unlockKey`'s post-#16 idempotency guard would no-op them anyway, but emitting "unlocked" log lines for keys that didn't need unlocking is noise. Updates `docs/AUTOUNLOCK.md` accordingly so the description matches the implementation. Refs aiolabs/nsecbunkerd#16. --- docs/AUTOUNLOCK.md | 13 ++++++++----- src/daemon/run.ts | 34 +++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/docs/AUTOUNLOCK.md b/docs/AUTOUNLOCK.md index 6e0bd1b..1c0552f 100644 --- a/docs/AUTOUNLOCK.md +++ b/docs/AUTOUNLOCK.md @@ -35,11 +35,14 @@ the autounlock pass runs: 1. Read the passphrase from the configured source. Failure to read (missing file, no permission) is fatal at boot. -2. Enumerate every row in the `Key` Prisma table where - `deletedAt IS NULL`. -3. For each row, call `unlockKey(keyName, passphrase)`. `unlockKey` - is idempotent post-#16: if the key was already unlocked by a - prior pass, it's a no-op. +2. Enumerate the encrypted-at-rest entries in `nsecbunker.json`'s + `keys` map — entries carrying the `{iv, data}` shape from + `create_new_key`. Plain-key entries (`{key: ...}` shape from + `create_account`) are already loaded by the existing + `startKeys()` passes and are skipped here for log clarity. +3. For each candidate, call `unlockKey(keyName, passphrase)`. + `unlockKey` is idempotent post-#16: if the key was already + unlocked by a prior pass, it's a no-op. 4. Log per-key INFO on success, WARN on `unlockKey → false` (typically: wrong passphrase, possibly the key was created under a historical passphrase that differs from the current one), ERROR on diff --git a/src/daemon/run.ts b/src/daemon/run.ts index 7945867..743606d 100644 --- a/src/daemon/run.ts +++ b/src/daemon/run.ts @@ -278,32 +278,52 @@ class Daemon { source = `NSEC_BUNKER_AUTOUNLOCK_PASSPHRASE_FILE=${filePath}`; } - const keys = await prisma.key.findMany({ where: { deletedAt: null } }); + // Enumerate encrypted-at-rest keys from `config.allKeys`. The + // Prisma `Key` table is only populated by the NIP-05 `create_account` + // path (which stores keys plain-at-rest in nsecbunker.json); + // `create_new_key` provisions keys with the `{iv, data}` encrypted + // shape directly into the JSON blob without a Prisma row. So the + // canonical "what's encrypted at rest" source is `allKeys` filtered + // to entries carrying `iv`+`data` — that's the set of keys for + // which the manual `unlock_key` admin RPC was previously required + // per restart, and exactly the set we want to autounlock here. + // + // Plain-key entries (`{key: "..."}` shape, populated by `create_account`) + // were already loaded by the second loop in `startKeys` above and + // appear in `activeKeys` — `unlockKey`'s idempotency guard makes + // re-calling them safe but unnecessary, so we filter them out for + // log clarity. + const candidates = Object.entries(this.config.allKeys || {}) + .filter(([, entry]) => + entry && typeof entry === 'object' && 'iv' in entry && 'data' in entry + ) + .map(([keyName]) => keyName); + const start = Date.now(); let success = 0; - for (const key of keys) { + for (const keyName of candidates) { try { - const ok = await this.unlockKey(key.keyName, passphrase); + const ok = await this.unlockKey(keyName, passphrase); if (ok) { - console.log(`🔓 autounlock: unlocked ${key.keyName}`); + console.log(`🔓 autounlock: unlocked ${keyName}`); success++; } else { console.warn( - `⚠️ autounlock: unlockKey returned false for ${key.keyName} ` + + `⚠️ autounlock: unlockKey returned false for ${keyName} ` + `(likely wrong passphrase — encrypted under a different secret?)` ); } } catch (e: any) { console.error( - `❌ autounlock: ${key.keyName} failed: ${e?.message ?? e}` + `❌ autounlock: ${keyName} failed: ${e?.message ?? e}` ); } } const elapsed = Date.now() - start; console.log( - `🔓 autounlock: enabled (source=${source}), unlocked ${success}/${keys.length} keys in ${elapsed}ms` + `🔓 autounlock: enabled (source=${source}), unlocked ${success}/${candidates.length} keys in ${elapsed}ms` ); } From 8ee0595ea850589556901c55961de53f409a431d Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 3 Jun 2026 14:51:40 +0200 Subject: [PATCH 25/36] fix(nix): build under pnpm_9 + drop stale NDK substitute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NDK 2.8.1 → 3.0.3 bump (041f431) regenerated pnpm-lock.yaml at lockfile v9, which pnpm_8 refuses to read. Switch the derivation to pnpm_9 and regen the pnpmDeps hash to match the v9 lockfile. The package.json/pnpm-lock realignment that `patchNdk` used to fix is no longer needed — the same bump also pinned NDK as `"3.0.3"` in package.json, so manifest + lockfile already agree. Drop the substitute (kept as a no-op shim for the next time a bump diverges them) instead of carrying a substituteStream that errors out under --replace-fail because the source string no longer exists. Co-Authored-By: Claude Opus 4.7 (1M context) --- package.nix | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/package.nix b/package.nix index adeb62b..d534666 100644 --- a/package.nix +++ b/package.nix @@ -1,7 +1,7 @@ { lib, stdenv, - pnpm_8, + pnpm_9, nodejs_20, makeWrapper, prisma-engines, @@ -13,19 +13,13 @@ }: let - # Fork commit `06272c8` ("pin @nostr-dev-kit/ndk to 2.8.1 instead of - # workspace:*") changed package.json to a pinned `"2.8.1"`, but the - # pnpm-lock.yaml still expresses the spec as `"^2.8.1"` (the way - # `pnpm add` originally generated it). pnpm with --frozen-lockfile - # rejects that mismatch. Patching package.json to use the caret form - # is non-semantic (2.8.1 is still the resolved version) and aligns - # both files. Same fix the Dockerfile-side already handles via - # `--no-frozen-lockfile`; in nix we prefer frozen + a targeted patch. - patchNdk = '' - substituteInPlace package.json \ - --replace-fail '"@nostr-dev-kit/ndk": "2.8.1"' \ - '"@nostr-dev-kit/ndk": "^2.8.1"' - ''; + # The NDK 2.8.1 → 3.0.3 bump (commit 041f431) regenerated pnpm-lock.yaml + # at lockfile v9 and pinned NDK as `"3.0.3"`. Lockfile + manifest agree + # post-bump, so the historical patch-back-to-caret-form is no longer + # required. Leave the no-op shim in place as a structural anchor; if a + # future bump regenerates the lockfile under a non-caret manifest spec + # again, this is the seam where the realignment goes. + patchNdk = ""; prismaEnv = { PRISMA_SCHEMA_ENGINE_BINARY = lib.getExe' prisma-engines "schema-engine"; @@ -42,18 +36,18 @@ stdenv.mkDerivation (finalAttrs: { src = ./.; - pnpmDeps = pnpm_8.fetchDeps { + pnpmDeps = pnpm_9.fetchDeps { inherit (finalAttrs) pname version src; fetcherVersion = 2; prePnpmInstall = patchNdk; - hash = "sha256-dQ+TX5jf1ZQKGoPCZgWaFwpAC3uP6iL1ZSxS0mFNdP8="; + hash = "sha256-nmjZ2oTw8K4lTA+2gdtWXX7TnM0n39OwvbwG3DBQ9WU="; }; postPatch = patchNdk; nativeBuildInputs = [ - pnpm_8.configHook - pnpm_8 + pnpm_9.configHook + pnpm_9 nodejs_20 makeWrapper node-gyp From 131f689c6ff14fbd4716ec3c29956cc82010a023 Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 3 Jun 2026 15:04:40 +0200 Subject: [PATCH 26/36] =?UTF-8?q?deps:=20bump=20prisma=205.4.1=20=E2=86=92?= =?UTF-8?q?=206.19.3=20(nix=20build=20fix)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Required to keep the nix package buildable: nixpkgs unstable no longer ships prisma-engines 5.x — the unsuffixed `prisma-engines` attr now aliases 7.x (no libquery_engine.node), and the only versioned attrs are `prisma-engines_6` (6.19.3) and `prisma-engines_7`. Bump both `@prisma/client` and `prisma` to ^6.19.0 so the client matches the only engine we can pin to. Also: - package.nix takes `prisma-engines_6` directly. flake.nix passes `pkgs.prisma-engines_6 or pkgs.prisma-engines` so the package still builds on nixos-25.05 (where prisma-engines is 6.7.0 unsuffixed). - Drop PRISMA_INTROSPECTION_ENGINE_BINARY — prisma 6 collapsed the introspection engine into schema-engine, the binary no longer ships. Schema is unchanged so existing fresh installs migrate identically. Existing dev instances with a prisma_5-tracked _prisma_migrations table will need a one-time `prisma migrate resolve` step on first boot under the new client; deploy targets are all fresh installs. Co-Authored-By: Claude Opus 4.7 (1M context) --- flake.nix | 8 +- package.json | 4 +- package.nix | 15 ++- pnpm-lock.yaml | 333 +++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 287 insertions(+), 73 deletions(-) diff --git a/flake.nix b/flake.nix index 5bb1222..02814d7 100644 --- a/flake.nix +++ b/flake.nix @@ -14,7 +14,13 @@ let pkgs = pkgsFor system; in rec { default = nsecbunkerd; - nsecbunkerd = pkgs.callPackage ./package.nix { }; + nsecbunkerd = pkgs.callPackage ./package.nix { + # nixos-unstable splits prisma-engines into versioned attrs and + # aliases the bare `prisma-engines` to 7.x (no libquery_engine + # for our 6.x client). nixos-25.05 has only the bare attr at + # 6.7.0. Pick whichever exists so the package builds on both. + prisma-engines_6 = pkgs.prisma-engines_6 or pkgs.prisma-engines; + }; } ); diff --git a/package.json b/package.json index b51595d..4975b68 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@inquirer/password": "^1.1.2", "@inquirer/prompts": "^1.2.3", "@nostr-dev-kit/ndk": "3.0.3", - "@prisma/client": "^5.4.1", + "@prisma/client": "^6.19.0", "@scure/base": "^1.1.1", "@types/yargs": "^17.0.24", "axios": "^1.6.2", @@ -65,7 +65,7 @@ "devDependencies": { "@types/debug": "^4.1.8", "@types/node": "^18.16.18", - "prisma": "^5.4.1", + "prisma": "^6.19.0", "ts-node": "^10.9.1", "tsup": "^7.2.0", "typescript": "^5.1.3" diff --git a/package.nix b/package.nix index d534666..5bf5fdb 100644 --- a/package.nix +++ b/package.nix @@ -4,7 +4,11 @@ pnpm_9, nodejs_20, makeWrapper, - prisma-engines, + # Pin to prisma-engines_6 (6.19.3) — package.json's `@prisma/client` + + # `prisma` are at ^6.19.0. The unversioned `prisma-engines` attr is now + # 7.x in nixpkgs which doesn't ship libquery_engine.node, so we'd fail + # at postinstall. + prisma-engines_6, openssl, sqlite, python311, @@ -13,6 +17,8 @@ }: let + prisma-engines = prisma-engines_6; + # The NDK 2.8.1 → 3.0.3 bump (commit 041f431) regenerated pnpm-lock.yaml # at lockfile v9 and pinned NDK as `"3.0.3"`. Lockfile + manifest agree # post-bump, so the historical patch-back-to-caret-form is no longer @@ -25,7 +31,10 @@ let PRISMA_SCHEMA_ENGINE_BINARY = lib.getExe' prisma-engines "schema-engine"; PRISMA_QUERY_ENGINE_BINARY = lib.getExe' prisma-engines "query-engine"; PRISMA_QUERY_ENGINE_LIBRARY = "${prisma-engines}/lib/libquery_engine.node"; - PRISMA_INTROSPECTION_ENGINE_BINARY = lib.getExe' prisma-engines "introspection-engine"; + # Prisma 6 collapsed introspection-engine into schema-engine — the + # binary no longer ships in prisma-engines_6. The env var is still + # honored if present (drops gracefully), but pointing it at a path + # that doesn't exist would fail at startup. PRISMA_FMT_BINARY = lib.getExe' prisma-engines "prisma-fmt"; PRISMA_CLIENT_ENGINE_TYPE = "binary"; }; @@ -40,7 +49,7 @@ stdenv.mkDerivation (finalAttrs: { inherit (finalAttrs) pname version src; fetcherVersion = 2; prePnpmInstall = patchNdk; - hash = "sha256-nmjZ2oTw8K4lTA+2gdtWXX7TnM0n39OwvbwG3DBQ9WU="; + hash = "sha256-DkFzzsQTuptRR8+rWfr9RGC+5XjSQrZlsZtspWfBW8w="; }; postPatch = patchNdk; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 13e81b0..ae755ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,8 +24,8 @@ importers: specifier: 3.0.3 version: 3.0.3(nostr-tools@2.20.0(typescript@5.9.3)) '@prisma/client': - specifier: ^5.4.1 - version: 5.22.0(prisma@5.22.0) + specifier: ^6.19.0 + version: 6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3) '@scure/base': specifier: ^1.1.1 version: 1.2.6 @@ -49,10 +49,10 @@ importers: version: 16.6.1 eslint-config-prettier: specifier: ^8.8.0 - version: 8.10.2(eslint@9.39.4) + version: 8.10.2(eslint@9.39.4(jiti@2.7.0)) eslint-plugin-import: specifier: ^2.27.5 - version: 2.32.0(eslint@9.39.4) + version: 2.32.0(eslint@9.39.4(jiti@2.7.0)) eventemitter3: specifier: ^5.0.1 version: 5.0.4 @@ -94,8 +94,8 @@ importers: specifier: ^18.16.18 version: 18.19.130 prisma: - specifier: ^5.4.1 - version: 5.22.0 + specifier: ^6.19.0 + version: 6.19.3(typescript@5.9.3) ts-node: specifier: ^10.9.1 version: 10.9.2(@types/node@18.19.130)(typescript@5.9.3) @@ -452,29 +452,35 @@ packages: '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} - '@prisma/client@5.22.0': - resolution: {integrity: sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==} - engines: {node: '>=16.13'} + '@prisma/client@6.19.3': + resolution: {integrity: sha512-mKq3jQFhjvko5LTJFHGilsuQs+W+T3Gm451NzuTDGQxwCzwXHYnIu2zGkRoW+Exq3Rob7yp2MfzSrdIiZVhrBg==} + engines: {node: '>=18.18'} peerDependencies: prisma: '*' + typescript: '>=5.1.0' peerDependenciesMeta: prisma: optional: true + typescript: + optional: true - '@prisma/debug@5.22.0': - resolution: {integrity: sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==} + '@prisma/config@6.19.3': + resolution: {integrity: sha512-CBPT44BjlQxEt8kiMEauji2WHTDoVBOKl7UlewXmUgBPnr/oPRZC3psci5chJnYmH0ivEIog2OU9PGWoki3DLQ==} - '@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2': - resolution: {integrity: sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==} + '@prisma/debug@6.19.3': + resolution: {integrity: sha512-ljkJ+SgpXNktLG0Q/n4JGYCkKf0f8oYLyjImS2I8e2q2WCfdRRtWER062ZV/ixaNP2M2VKlWXVJiGzZaUgbKZw==} - '@prisma/engines@5.22.0': - resolution: {integrity: sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==} + '@prisma/engines-version@7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7': + resolution: {integrity: sha512-03bgb1VD5gvuumNf+7fVGBzfpJPjmqV423l/WxsWk2cNQ42JD0/SsFBPhN6z8iAvdHs07/7ei77SKu7aZfq8bA==} - '@prisma/fetch-engine@5.22.0': - resolution: {integrity: sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==} + '@prisma/engines@6.19.3': + resolution: {integrity: sha512-RSYxtlYFl5pJ8ZePgMv0lZ9IzVCOdTPOegrs2qcbAEFrBI1G33h6wyC9kjQvo0DnYEhEVY0X4LsuFHXLKQk88g==} - '@prisma/get-platform@5.22.0': - resolution: {integrity: sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==} + '@prisma/fetch-engine@6.19.3': + resolution: {integrity: sha512-tKtl/qco9Nt7LU5iKhpultD8O4vMCZcU2CHjNTnRrL1QvSUr5W/GcyFPjNL87GtRrwBc7ubXXD9xy4EvLvt8JA==} + + '@prisma/get-platform@6.19.3': + resolution: {integrity: sha512-xFj1VcJ1N3MKooOQAGO0W5tsd0W2QzIvW7DD7c/8H14Zmp4jseeWAITm+w2LLoLrlhoHdPPh0NMZ8mfL6puoHA==} '@rollup/rollup-android-arm-eabi@4.60.4': resolution: {integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==} @@ -510,79 +516,66 @@ packages: resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.60.4': resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.60.4': resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.60.4': resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.60.4': resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.60.4': resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==} cpu: [loong64] os: [linux] - libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.60.4': resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.60.4': resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==} cpu: [ppc64] os: [linux] - libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.60.4': resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.60.4': resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.60.4': resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.60.4': resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.60.4': resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openbsd-x64@4.60.4': resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==} @@ -650,6 +643,9 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@tsconfig/node10@1.0.12': resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} @@ -890,6 +886,14 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} + c12@3.1.0: + resolution: {integrity: sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==} + peerDependencies: + magicast: ^0.3.5 + peerDependenciesMeta: + magicast: + optional: true + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -930,10 +934,20 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} + citty@0.1.6: + resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + + citty@0.2.2: + resolution: {integrity: sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==} + cli-spinners@2.9.2: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} @@ -971,6 +985,13 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + confbox@0.2.4: + resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} @@ -1043,6 +1064,10 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deepmerge-ts@7.1.5: + resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==} + engines: {node: '>=16.0.0'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -1051,6 +1076,9 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -1066,6 +1094,9 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -1100,9 +1131,16 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + effect@3.21.0: + resolution: {integrity: sha512-PPN80qRokCd1f015IANNhrwOnLO7GrrMQfk4/lnZRE/8j7UPWrNNjPV0uBrZutI/nHzernbW+J0hdqQysHiSnQ==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + empathic@2.0.0: + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} + encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -1270,6 +1308,9 @@ packages: resolution: {integrity: sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==} engines: {node: '>= 0.10.0'} + exsolve@1.0.8: + resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} + ext@1.7.0: resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} @@ -1277,6 +1318,10 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} + fast-check@3.23.2: + resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} + engines: {node: '>=8.0.0'} + fast-content-type-parse@1.1.0: resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} @@ -1433,6 +1478,10 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} + giget@2.0.0: + resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} + hasBin: true + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1680,6 +1729,10 @@ packages: peerDependencies: ws: '*' + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -1875,6 +1928,9 @@ packages: resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==} engines: {node: '>= 0.4'} + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -1916,6 +1972,11 @@ packages: resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} deprecated: This package is no longer supported. + nypm@0.6.6: + resolution: {integrity: sha512-vRyr0r4cbBapw07Xw8xrj9Teq3o7MUD35rSaTcanDbW+aK2XHDgJFiU6ZTj2GBw7Q12ysdsyFss+Vdz4hQ0Y6Q==} + engines: {node: '>=18'} + hasBin: true + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1948,6 +2009,9 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -2022,6 +2086,12 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + picomatch@2.3.2: resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} @@ -2044,6 +2114,9 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} + pkg-types@2.3.1: + resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==} + possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -2064,10 +2137,15 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prisma@5.22.0: - resolution: {integrity: sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==} - engines: {node: '>=16.13'} + prisma@6.19.3: + resolution: {integrity: sha512-++ZJ0ijLrDJF6hNB4t4uxg2br3fC4H9Yc9tcbjr2fcNFP3rh/SBNrAgjhsqBU4Ght8JPrVofG/ZkXfnSfnYsFg==} + engines: {node: '>=18.18'} hasBin: true + peerDependencies: + typescript: '>=5.1.0' + peerDependenciesMeta: + typescript: + optional: true process-warning@3.0.0: resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} @@ -2090,6 +2168,9 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + qs@6.15.2: resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} engines: {node: '>=0.6'} @@ -2108,6 +2189,9 @@ packages: resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} engines: {node: '>= 0.8'} + rc9@2.1.2: + resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -2116,6 +2200,10 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + real-require@0.2.0: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} @@ -2389,6 +2477,10 @@ packages: thread-stream@3.1.0: resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} @@ -2771,9 +2863,9 @@ snapshots: '@esbuild/win32-x64@0.19.12': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4)': + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.7.0))': dependencies: - eslint: 9.39.4 + eslint: 9.39.4(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -3049,30 +3141,40 @@ snapshots: '@pinojs/redact@0.4.0': {} - '@prisma/client@5.22.0(prisma@5.22.0)': + '@prisma/client@6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3)': optionalDependencies: - prisma: 5.22.0 + prisma: 6.19.3(typescript@5.9.3) + typescript: 5.9.3 - '@prisma/debug@5.22.0': {} - - '@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2': {} - - '@prisma/engines@5.22.0': + '@prisma/config@6.19.3': dependencies: - '@prisma/debug': 5.22.0 - '@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 - '@prisma/fetch-engine': 5.22.0 - '@prisma/get-platform': 5.22.0 + c12: 3.1.0 + deepmerge-ts: 7.1.5 + effect: 3.21.0 + empathic: 2.0.0 + transitivePeerDependencies: + - magicast - '@prisma/fetch-engine@5.22.0': - dependencies: - '@prisma/debug': 5.22.0 - '@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 - '@prisma/get-platform': 5.22.0 + '@prisma/debug@6.19.3': {} - '@prisma/get-platform@5.22.0': + '@prisma/engines-version@7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7': {} + + '@prisma/engines@6.19.3': dependencies: - '@prisma/debug': 5.22.0 + '@prisma/debug': 6.19.3 + '@prisma/engines-version': 7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7 + '@prisma/fetch-engine': 6.19.3 + '@prisma/get-platform': 6.19.3 + + '@prisma/fetch-engine@6.19.3': + dependencies: + '@prisma/debug': 6.19.3 + '@prisma/engines-version': 7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7 + '@prisma/get-platform': 6.19.3 + + '@prisma/get-platform@6.19.3': + dependencies: + '@prisma/debug': 6.19.3 '@rollup/rollup-android-arm-eabi@4.60.4': optional: true @@ -3199,6 +3301,8 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} + '@standard-schema/spec@1.1.0': {} + '@tsconfig/node10@1.0.12': {} '@tsconfig/node12@1.0.11': {} @@ -3469,6 +3573,21 @@ snapshots: bytes@3.1.2: {} + c12@3.1.0: + dependencies: + chokidar: 4.0.3 + confbox: 0.2.4 + defu: 6.1.7 + dotenv: 16.6.1 + exsolve: 1.0.8 + giget: 2.0.0 + jiti: 2.7.0 + ohash: 2.0.11 + pathe: 2.0.3 + perfect-debounce: 1.0.0 + pkg-types: 2.3.1 + rc9: 2.1.2 + cac@6.7.14: {} call-bind-apply-helpers@1.0.2: @@ -3515,8 +3634,18 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + chownr@2.0.0: {} + citty@0.1.6: + dependencies: + consola: 3.4.2 + + citty@0.2.2: {} + cli-spinners@2.9.2: {} cli-width@4.1.0: {} @@ -3545,6 +3674,10 @@ snapshots: concat-map@0.0.1: {} + confbox@0.2.4: {} + + consola@3.4.2: {} + console-control-strings@1.1.0: {} content-disposition@0.5.4: @@ -3604,6 +3737,8 @@ snapshots: deep-is@0.1.4: {} + deepmerge-ts@7.1.5: {} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.1 @@ -3616,6 +3751,8 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 + defu@6.1.7: {} + delayed-stream@1.0.0: {} delegates@1.0.0: {} @@ -3624,6 +3761,8 @@ snapshots: dequal@2.0.3: {} + destr@2.0.5: {} + destroy@1.2.0: {} detect-libc@2.1.2: {} @@ -3652,8 +3791,15 @@ snapshots: ee-first@1.1.1: {} + effect@3.21.0: + dependencies: + '@standard-schema/spec': 1.1.0 + fast-check: 3.23.2 + emoji-regex@8.0.0: {} + empathic@2.0.0: {} + encodeurl@2.0.0: {} es-abstract@1.24.2: @@ -3790,9 +3936,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@8.10.2(eslint@9.39.4): + eslint-config-prettier@8.10.2(eslint@9.39.4(jiti@2.7.0)): dependencies: - eslint: 9.39.4 + eslint: 9.39.4(jiti@2.7.0) eslint-import-resolver-node@0.3.10: dependencies: @@ -3802,16 +3948,16 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.13.0(eslint-import-resolver-node@0.3.10)(eslint@9.39.4): + eslint-module-utils@2.13.0(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@2.7.0)): dependencies: debug: 3.2.7 optionalDependencies: - eslint: 9.39.4 + eslint: 9.39.4(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(eslint@9.39.4): + eslint-plugin-import@2.32.0(eslint@9.39.4(jiti@2.7.0)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -3820,9 +3966,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.39.4 + eslint: 9.39.4(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 - eslint-module-utils: 2.13.0(eslint-import-resolver-node@0.3.10)(eslint@9.39.4) + eslint-module-utils: 2.13.0(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@2.7.0)) hasown: 2.0.4 is-core-module: 2.16.2 is-glob: 4.0.3 @@ -3847,9 +3993,9 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.4: + eslint@9.39.4(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.2 '@eslint/config-helpers': 0.4.2 @@ -3883,6 +4029,8 @@ snapshots: minimatch: 3.1.5 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.7.0 transitivePeerDependencies: - supports-color @@ -3968,6 +4116,8 @@ snapshots: transitivePeerDependencies: - supports-color + exsolve@1.0.8: {} + ext@1.7.0: dependencies: type: 2.7.3 @@ -3978,6 +4128,10 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 + fast-check@3.23.2: + dependencies: + pure-rand: 6.1.0 + fast-content-type-parse@1.1.0: {} fast-decode-uri-component@1.0.1: {} @@ -4169,6 +4323,15 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 + giget@2.0.0: + dependencies: + citty: 0.1.6 + consola: 3.4.2 + defu: 6.1.7 + node-fetch-native: 1.6.7 + nypm: 0.6.6 + pathe: 2.0.3 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -4432,6 +4595,8 @@ snapshots: dependencies: ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + jiti@2.7.0: {} + joycon@3.1.1: {} js-yaml@4.1.1: @@ -4613,6 +4778,8 @@ snapshots: object.entries: 1.1.9 semver: 6.3.1 + node-fetch-native@1.6.7: {} + node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 @@ -4650,6 +4817,12 @@ snapshots: gauge: 3.0.2 set-blocking: 2.0.0 + nypm@0.6.6: + dependencies: + citty: 0.2.2 + pathe: 2.0.3 + tinyexec: 1.2.4 + object-assign@4.1.1: {} object-inspect@1.13.4: {} @@ -4692,6 +4865,8 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.2 + ohash@2.0.11: {} + on-exit-leak-free@2.1.2: {} on-finished@2.4.1: @@ -4759,6 +4934,10 @@ snapshots: path-type@4.0.0: {} + pathe@2.0.3: {} + + perfect-debounce@1.0.0: {} + picomatch@2.3.2: {} picomatch@4.0.4: {} @@ -4785,6 +4964,12 @@ snapshots: pirates@4.0.7: {} + pkg-types@2.3.1: + dependencies: + confbox: 0.2.4 + exsolve: 1.0.8 + pathe: 2.0.3 + possible-typed-array-names@1.1.0: {} postcss-load-config@4.0.2(ts-node@10.9.2(@types/node@18.19.130)(typescript@5.9.3)): @@ -4796,11 +4981,14 @@ snapshots: prelude-ls@1.2.1: {} - prisma@5.22.0: + prisma@6.19.3(typescript@5.9.3): dependencies: - '@prisma/engines': 5.22.0 + '@prisma/config': 6.19.3 + '@prisma/engines': 6.19.3 optionalDependencies: - fsevents: 2.3.3 + typescript: 5.9.3 + transitivePeerDependencies: + - magicast process-warning@3.0.0: {} @@ -4817,6 +5005,8 @@ snapshots: punycode@2.3.1: {} + pure-rand@6.1.0: {} + qs@6.15.2: dependencies: side-channel: 1.1.0 @@ -4834,6 +5024,11 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + rc9@2.1.2: + dependencies: + defu: 6.1.7 + destr: 2.0.5 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -4844,6 +5039,8 @@ snapshots: dependencies: picomatch: 2.3.2 + readdirp@4.1.2: {} + real-require@0.2.0: {} reflect.getprototypeof@1.0.10: @@ -5196,6 +5393,8 @@ snapshots: dependencies: real-require: 0.2.0 + tinyexec@1.2.4: {} + tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.4) From a690596b857301ed34f0f13ec2b263bdbe2c7436 Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 3 Jun 2026 18:55:55 +0200 Subject: [PATCH 27/36] fix(daemon): keep retrying relay reconnect indefinitely, overriding NDK give-up (#20) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NDK 3.x's per-relay connectivity machine gives up after ~3 fast-fail (ECONNREFUSED) cycles. Three sub-second failures look identical, so `isFlapping()` (std-dev < 1s) returns true and the relay transitions to FLAPPING; NDKPool's `handleFlapping` then reschedules with doubling backoff (5s → 10s → 20s → 40s → 80s …). For nsecbunkerd, "disconnected for 80+s after every lnbits restart" is the failure mode users hit on the regtest dev stack: bunker container boots before lnbits's nostrrelay extension is accepting WebSockets → ECONNREFUSED storm → NDK flagged FLAPPING → bunker stays silently deaf until manual restart. Symptom is particularly hostile because: - `relay:connect` fires optimistically; the immediate ECONNREFUSED follow-up doesn't propagate to user-facing logs. - `NSEC_BUNKER_DISABLE_WATCHDOG=1` (the dev-stack default) skips the exit-and-restart safety net. - Manual `docker compose restart nsecbunker` is the only recovery. Fix: attach a small supervisor (`attachIndefiniteReconnect`) to both NDK instances (daemon's backend NDK in run.ts, AdminInterface's admin NDK in admin/index.ts). On `relay:disconnect` or `flapping`, schedule a manual `relay.connect()` with a SHORT capped delay (1s → 2s → 4s → 8s → 10s, capped at 10s instead of NDK's unbounded doubling). Successful connect resets the attempt counter so a future disconnect storm starts fresh. Coexists cleanly with the relay-connection watchdog (admin/index.ts:500): - Brief disconnects (e.g. lnbits restart): supervisor recovers within seconds, watchdog never fires. - Persistent disconnects (relay truly down): supervisor keeps trying every ≤10s; if it can't recover within 60s, watchdog still exits and the process supervisor restarts the bunker. So the watchdog becomes a long-tail safety net; this supervisor handles the common case. Operators with `NSEC_BUNKER_DISABLE_WATCHDOG=1` set as a workaround for this bug can re-enable the watchdog once this lands. Trade-off: we may hammer a permanently-down relay every 10s. Acceptable because the bunker's primary relay is typically on the same host or LAN (loopback or docker-internal); TCP RSTs are cheap. Public-relay setups can layer external supervision on top. Verified on regtest dev stack (cold-boot race): bunker logs 🔁 admin: scheduling reconnect to ws://lnbits:5001/nostrrelay/test/ in 1000ms (attempt 1, overriding NDK give-up) 🔁 backend: scheduling reconnect to ws://lnbits:5001/nostrrelay/test/ in 1000ms (attempt 1, overriding NDK give-up) on each disconnect, where pre-fix the bunker stayed silently deaf. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/admin/index.ts | 10 +++ src/daemon/lib/relay-reconnect.ts | 101 ++++++++++++++++++++++++++++++ src/daemon/run.ts | 7 +++ 3 files changed, 118 insertions(+) create mode 100644 src/daemon/lib/relay-reconnect.ts diff --git a/src/daemon/admin/index.ts b/src/daemon/admin/index.ts index e4d8509..a918a66 100644 --- a/src/daemon/admin/index.ts +++ b/src/daemon/admin/index.ts @@ -25,6 +25,7 @@ import { validateRequestFromAdmin } from './validations/request-from-admin'; import { dmUser } from '../../utils/dm-user'; import { IConfig, getCurrentConfig } from "../../config"; import path from 'path'; +import { attachIndefiniteReconnect } from '../lib/relay-reconnect.js'; const debug = createDebug("nsecbunker:admin"); @@ -62,6 +63,15 @@ class AdminInterface { explicitRelayUrls: opts.adminRelays, signer: new NDKPrivateKeySigner(opts.key), }); + + // Override NDK's "give up after detecting flapping" behavior so the + // bunker's admin NDK keeps trying to reconnect indefinitely. The + // watchdog (when enabled) still fires after 60s of zero connected + // relays; this helper handles shorter disconnects (e.g. an lnbits + // restart that pulls the nostrrelay extension's WS for a few + // seconds) without involving the supervisor. See aiolabs/nsecbunkerd#20. + attachIndefiniteReconnect(this.ndk, 'admin'); + this.ndk.signer?.user().then((user: NDKUser) => { let connectionString = `bunker://${user.npub}`; diff --git a/src/daemon/lib/relay-reconnect.ts b/src/daemon/lib/relay-reconnect.ts new file mode 100644 index 0000000..e3fdb4f --- /dev/null +++ b/src/daemon/lib/relay-reconnect.ts @@ -0,0 +1,101 @@ +import NDK from "@nostr-dev-kit/ndk"; + +/** + * Attaches an aggressive-reconnect supervisor to an NDK instance. + * + * NDK 3.x's per-relay connectivity state machine gives up retrying after + * a few consecutive fast-fail (e.g. ECONNREFUSED returns in <1 ms) + * connection attempts: + * + * 1. Each attempt's duration is recorded in `_connectionStats.durations`. + * 2. After every 3 attempts, `isFlapping()` checks the std-dev of those + * durations against `FLAPPING_THRESHOLD_MS` (1 second). Three fast + * failures look identical → tiny std-dev → flapping=true → status + * transitions to FLAPPING and the per-relay retry stops. + * 3. `NDKPool.handleFlapping` catches the event and reschedules a + * reconnect via doubling backoff (5s → 10s → 20s → 40s → 80s …), + * growing unbounded. + * + * For nsecbunkerd, where the admin relay is typically a single relay we + * **must** stay subscribed to, "disconnected for 80+s after every dev + * restart" is the failure mode users hit (aiolabs/nsecbunkerd#20). The + * pool's doubling backoff is too pessimistic for our use case. + * + * This helper sidesteps the give-up path: when the pool emits `flapping` + * (the symptom that NDK has internally given up), or when we see the + * relay disconnect outside our own request, we manually call + * `relay.connect()` with a SHORT capped delay. Successful connect resets + * the attempt counter so a future disconnect storm doesn't grow the + * delay. + * + * Trade-off: we may hammer a permanently-down relay every 10s. That's + * fine for a bunker — being disconnected silently is strictly worse than + * a retry storm against localhost. Acceptable because: + * - The bunker's primary relay is typically on the same host or LAN + * (`ws://lnbits:5001/...`); TCP RSTs are cheap. + * - Public-relay setups can layer external supervision on top if they + * care about retry pressure. + */ +export function attachIndefiniteReconnect(ndk: NDK, label: string): void { + const RECONNECT_BASE_MS = 1_000; + const RECONNECT_CAP_MS = 10_000; + + const attempts = new Map(); + const pending = new Map(); + + const reconnectDelay = (n: number): number => + Math.min(RECONNECT_BASE_MS * 2 ** n, RECONNECT_CAP_MS); + + const scheduleReconnect = (relay: any): void => { + const url: string = relay.url; + if (pending.has(url)) return; + const n = attempts.get(url) ?? 0; + const delay = reconnectDelay(n); + console.log( + `🔁 ${label}: scheduling reconnect to ${url} in ${delay}ms ` + + `(attempt ${n + 1}, overriding NDK give-up)` + ); + const timer = setTimeout(() => { + pending.delete(url); + attempts.set(url, n + 1); + relay.connect().catch((e: any) => { + console.log( + `❌ ${label}: manual reconnect to ${url} failed: ` + + `${e?.message ?? e}` + ); + // Don't recurse here — the next 'flapping' or 'disconnect' + // event will fire and schedule another attempt. + }); + }, delay); + pending.set(url, timer); + }; + + ndk.pool.on("flapping", (relay: any) => { + console.log( + `⚠️ ${label}: NDK flagged ${relay.url} as flapping ` + + `(connectivity machine gave up internally)` + ); + scheduleReconnect(relay); + }); + + ndk.pool.on("relay:disconnect", (relay: any) => { + scheduleReconnect(relay); + }); + + ndk.pool.on("relay:connect", (relay: any) => { + const url: string = relay.url; + const n = attempts.get(url) ?? 0; + if (n > 0) { + console.log( + `✅ ${label}: recovered ${url} after ${n} manual reconnect ` + + `attempt(s)` + ); + } + attempts.delete(url); + const timer = pending.get(url); + if (timer) { + clearTimeout(timer); + pending.delete(url); + } + }); +} diff --git a/src/daemon/run.ts b/src/daemon/run.ts index 743606d..7eaa512 100644 --- a/src/daemon/run.ts +++ b/src/daemon/run.ts @@ -15,6 +15,7 @@ import FastifyView from '@fastify/view'; import Handlebars from "handlebars"; import {authorizeRequestWebHandler, processRequestWebHandler} from "./web/authorize.js"; import {processRegistrationWebHandler} from "./web/authorize.js"; +import { attachIndefiniteReconnect } from "./lib/relay-reconnect.js"; export type Key = { name: string; @@ -165,6 +166,12 @@ class Daemon { this.ndk.pool.on('relay:disconnect', (r) => { console.log(`🚫 Disconnected from ${r.url}`); }); + + // Override NDK's "give up after detecting flapping" behavior so the + // bunker's backend NDK keeps trying to reconnect indefinitely. + // Without this, an ECONNREFUSED storm at boot (relay not yet up) + // permanently strands the bunker. See aiolabs/nsecbunkerd#20. + attachIndefiniteReconnect(this.ndk, 'backend'); } async startWebAuth() { From 59e90d07c09862a709475b02c69d4c6f4c7bd462 Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 3 Jun 2026 19:05:03 +0200 Subject: [PATCH 28/36] fix(backend): pin per-key kind:24133 subscription to explicit relays (#21) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Backend.start()` calls `this.ndk.subscribe(filter, opts)` to listen for NIP-46 events targeted at each unlocked key's pubkey (kind:24133 with `#p=[localUser.pubkey]`). Pre-fix this subscription opts didn't pin a relay set, so NDK 3.x's outbox routing kicked in: it looked up the `localUser.pubkey`'s NIP-65 relay list (kind:10002) to decide where to send the REQ. Newly-provisioned bunker keys have no kind:10002 published yet, so NDK's subscription manager queued the REQ waiting for a relay list that would never arrive — the subscription never landed on the wire. The user-visible symptom: every NIP-46 RPC from lnbits to a freshly- provisioned key (`connect`, `get_public_key`, `sign_event`, the `nip04_*` / `nip44_*` family) was published into the relay, the relay tried to route, found no subscribed peer matching `["p", new_key_pubkey]`, and emitted "Filter didn't match". The lnbits-side RPC then timed out at 15s, breaking eager merchant provisioning (aiolabs/lnbits#46) and satmachineadmin's per-cassette `nip44_decrypt` polling. Reproduced + diagnosed by patching the lnbits `nostrrelay` extension's `_handle_request` to log incoming REQ filters: only the admin subscription (`{kinds:[24133,24134], #p:[bunker_admin_pubkey]}` from `AdminInterface.connect()`) appeared on the wire. The per-key Backend filters from `Backend.start()` did not. Fix: pass `relayUrls: this.ndk.explicitRelayUrls` in the subscription opts. `relayUrls` was added in NDK 2.13.0 as the supported way to bypass outbox routing per subscription; the relay set built from these URLs matches what the rest of the daemon uses (admin RPC channel + every per-key Backend channel), so events flow through the same connection the admin interface already established. Verified on the regtest dev stack with bunker enabled, fresh signup provisioning a new key + immediately publishing a kind:30017 stall via NIP-46 sign_event: POST /auth/register → HTTP 200 in 1.1s stalls.event_id = 8a2eb20b929… (populated by bunker signature) relay sees: nostr event: [30017, , '{...store...}'] Pre-fix this same flow timed out at `NsecBunkerTimeoutError: no NIP-46 response for 'sign_event' within 15.0s`. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/backend/index.ts | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/daemon/backend/index.ts b/src/daemon/backend/index.ts index 49112fc..5d05a8a 100644 --- a/src/daemon/backend/index.ts +++ b/src/daemon/backend/index.ts @@ -45,12 +45,36 @@ export class Backend extends NDKNip46Backend { async start(): Promise { this.localUser = await this.signer.user(); await new Promise((resolve) => { + // Pin this subscription to the daemon's explicit relays via + // `relayUrls`. Without that, NDK 3.x's outbox routing tries to + // resolve the relay set from `this.localUser.pubkey`'s NIP-65 + // relay list (kind:10002). Newly-provisioned bunker keys have + // no published kind:10002 yet, so NDK's subscription manager + // queues the REQ waiting for a relay list that will never + // arrive — the kind:24133 subscription never lands on the + // wire, and inbound NIP-46 events (sign_event, get_public_key, + // nip44_*) targeted at this key get dropped by the relay + // with "Filter didn't match" because the bunker isn't actually + // subscribed for them. + // + // `relayUrls` was added in NDK 2.13.0 as the supported way to + // bypass outbox routing per subscription (see + // NDKSubscriptionOptions.relayUrls in @nostr-dev-kit/ndk). + // The relay set built from these URLs matches what the rest + // of the bunker uses (admin RPC channel + per-key Backend + // channels alike), so events flow through the same connection + // the admin interface already established. + // + // See aiolabs/nsecbunkerd#21. const sub = this.ndk.subscribe( { kinds: [24133], "#p": [this.localUser!.pubkey], }, - { closeOnEose: false } + { + closeOnEose: false, + relayUrls: this.ndk.explicitRelayUrls, + } ); sub.on("event", (e: any) => this.handleIncomingEvent(e)); sub.on("eose", () => resolve()); From 8326a16ea9e0ad36799525ee7d2b8cc1056abcba Mon Sep 17 00:00:00 2001 From: Padreug Date: Fri, 19 Jun 2026 14:54:18 +0200 Subject: [PATCH 29/36] docs(#25): add lnbits/nostr_bunker comparison (prior art) Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/COMPARISON-lnbits-nostr_bunker.md | 108 +++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 docs/COMPARISON-lnbits-nostr_bunker.md diff --git a/docs/COMPARISON-lnbits-nostr_bunker.md b/docs/COMPARISON-lnbits-nostr_bunker.md new file mode 100644 index 0000000..5aa6d77 --- /dev/null +++ b/docs/COMPARISON-lnbits-nostr_bunker.md @@ -0,0 +1,108 @@ +# nsecbunkerd vs. `lnbits/nostr_bunker` + +A comparison of this daemon (the aiolabs fork of `kind-0/nsecbunkerd`) against the +upstream LNbits extension [`lnbits/nostr_bunker`](https://github.com/lnbits/nostr_bunker). + +> Source verified 2026-06-19 against `lnbits/nostr_bunker@main` (`services.py`, +> `models.py`, `crud.py`). The two projects share a name and a NIP (NIP-46 remote +> signing) but are architecturally **inverted**: this daemon *uses* LNbits as a +> downstream wallet provider; the upstream extension *is* an LNbits extension that +> turns a wallet account into the bunker. + +## The one thing that matters: where the nsec lives + +| | nsecbunkerd (this fork) | `lnbits/nostr_bunker` | +|---|---|---| +| **Signing key location** | On the **daemon** host, separate process from LNbits | On the **LNbits** host, inside the extension DB | +| **At-rest protection** | Passphrase-encrypted (LND-style unlock) for manually-added keys | **Plaintext** in `nostr_bunker.bunkers_data.nsec` — no encryption | +| **Integration direction** | LNbits is a *downstream dependency* (wallet factory) | LNbits is the *host* (wallet account = signer identity) | + +`crud.py:create_bunkers_data()` writes the nsec straight through +`db.insert("nostr_bunker.bunkers_data", ...)` with no encryption step; `models.py` +`BunkersData.nsec` is "the normalized private key stored directly." This is the exact +posture the aiolabs roadmap (`aiolabs/lnbits#18`, "no nsec at rest on LNbits") exists +to eliminate: the LNbits host runs extension code, payment plumbing, and a public API, +so disk/root compromise there must NOT equal Nostr-identity compromise. The +standalone-daemon model keeps signing off that host; the upstream extension puts the +key right back on it, unencrypted. + +## Full side-by-side + +| Dimension | nsecbunkerd (this fork) | `lnbits/nostr_bunker` | +|---|---|---| +| **Form factor** | Standalone Node daemon (own process/container) | LNbits extension, runs inside the LNbits process | +| **Stack** | TypeScript + NDK 3.0.3 + nostr-tools 2.20 + Prisma/SQLite | Python + Vue/Quasar UMD frontend | +| **Relay transport** | Daemon opens its own relay connections (NDK); per-key kind:24133 subs pinned to explicit relays (#21) | Piggybacks the `nostrclient` extension's shared relay layer (`nostr_client.relay_manager.publish_message()`) | +| **Tenancy** | Multi-key, multi-domain, multi-user from one daemon | One bunker per wallet account; multiplexes clients via multiple `bunker://` URLs | +| **Admin / control plane** | Whitelisted admin npubs over E2E-encrypted Nostr events; separate bunker key holds no user key material; optional remote `app.nsecbunker.com` UI | LNbits admin UI; wallet owner is implicitly the operator | +| **Account provisioning** | OAuth-like flow: remote `create_account` → NIP-05 file write → NIP-89 (`kind:31990`) announce → mints LNbits wallet via `usermanager` API + nostdress `lud16` | None — the LNbits account already exists; the wallet *is* the identity | + +## NIP-46 surface + +Both implement NIP-46 over kind:24133 and accept **both** NIP-04 and NIP-44 v2 +(upstream `services.py` tries `nip44_decrypt` first, falls back to `nip04_decrypt`). + +| Method | nsecbunkerd | `lnbits/nostr_bunker` | +|---|---|---| +| `connect` | ✓ | ✓ (returns secret/ack after permission check) | +| `get_public_key` | ✓ | ✓ | +| `sign_event` | ✓ (ACL-gated, wire-name vocab #14) | ✓ (`_assert_method_allowed` + auto/confirm flow) | +| `nip04_encrypt` / `decrypt` | ✓ | ✓ | +| `nip44_encrypt` / `decrypt` | ✓ | ✓ | +| `ping` | ✓ | ✓ (`pong`) | +| `switch_relays` | — | ✓ (returns relay list as JSON) | + +## Policy / permission model + +This is where the designs genuinely diverge, and where upstream has something worth +borrowing. + +**nsecbunkerd** — relational ACL across several tables: +- `KeyUser` — a (keyName, userPubkey) grant +- `SigningCondition` — per-method/kind/content allow rules +- `Policy` / `PolicyRule` — reusable rule sets with per-rule `maxUsageCount` + expiry +- `Token` — redeemable connection grant bound to a policy, with `redeemedAt` / `revokedAt` +- Live-policy auth re-evaluated at request time (#11) + +**`lnbits/nostr_bunker`** — policy is **the `bunker://` URL itself**. Each `UrlData` +row carries its own: +- `relays`, `secret`, `client_pubkey` +- `permissions` (e.g. `sign_event:{kind}`), `can_read`, `can_write` +- `auto_sign` (default `False`) vs `confirm_sign` (default `True`) +- `expires_at` +- `post_rate_limit_per_day` — daily cap on kind:1, enforced by counting + `get_signing_requests_since()` over 24h (`_assert_post_rate_limit`) + +Pending approvals live in `SigningRequest` (status: pending/approved/signed/rejected/error), +mirroring this fork's `Request` + manual-approval flow. + +**Takeaway:** upstream's "one bunker, many scoped URLs, each URL is a self-contained +grant" is arguably cleaner than this fork's `Token`+`Policy`+`SigningCondition` triad +for the common case of "issue a narrowly-scoped grant to one client." If the ACL surface +here is ever simplified, that URL-as-grant model is the reference design — note in +particular the built-in `post_rate_limit_per_day`, which this fork has no direct +equivalent for. + +## Where each fits the aiolabs stack + +- **nsecbunkerd is the signer; LNbits is a client of it.** This is the `#18` endgame: + LNbits routes signing through a `RemoteBunkerSigner` over NIP-46 (the + protocol-over-loopback boundary chosen deliberately over a Unix socket), and every + nsec — operator *and* server identity — is retired from the LNbits host. + +- **`lnbits/nostr_bunker` is the convenience inversion we're explicitly avoiding.** + Useful prior art for per-URL policy ergonomics, but adopting it as the *signer + location* would reintroduce plaintext nsec-at-rest on the payments host — the precise + thing `#18` is designed to kill. + +## Gaps to track on our side + +1. **OAuth-created keys are stored recoverable, not encrypted.** + `create_account.ts` writes `currentConfig.keys[keyName] = { key: key.privateKey }`, + unlike the passphrase-encrypted path the SECURITY-MODEL doc describes for + manually-added keys. The doc promises non-exfiltratable keys; the OAuth path doesn't + meet that bar. (We're still strictly better than upstream, which stores *all* nsecs + plaintext — but the doc/behavior gap is real.) + +2. **No per-grant rate limiting.** Upstream's `post_rate_limit_per_day` is a clean + primitive we lack. Worth considering as a `PolicyRule` field. From a707d203a1be6fe7477020ca591700e1d07f4270 Mon Sep 17 00:00:00 2001 From: Padreug Date: Fri, 19 Jun 2026 14:54:18 +0200 Subject: [PATCH 30/36] docs(#25): source-verified ACL prior-art survey + keep-our-fork decision Surveys Signet, Amber, FROSTR, promenade, NDK/rust-nostr/nak against actual source; records the decision to keep our fork and treat Signet as a parts donor (NIP-46 wire boundary keeps the signer substitutable). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/acl-prior-art-survey.md | 297 +++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 docs/acl-prior-art-survey.md diff --git a/docs/acl-prior-art-survey.md b/docs/acl-prior-art-survey.md new file mode 100644 index 0000000..01a9f57 --- /dev/null +++ b/docs/acl-prior-art-survey.md @@ -0,0 +1,297 @@ +# ACL prior-art survey — NIP-46 bunker implementations + +Source-verified survey of how other open-source NIP-46 remote signers model +authorization and grant lifecycle, run to inform the #25 ACL redesign (enforce +token + grant lifecycle live at sign time instead of via a materialized cache). + +> **Verification status.** Every claim below was read against actual source on +> 2026-06-19 (clones at the commits noted per project). An initial automated +> survey overstated several implementations (notably "Signet enforces all +> lifecycle live" — false); the corrections are called out inline. Treat the +> file:line citations as the authority, not the prose summaries. + +## TL;DR for the redesign + +- **Amber** is the one *positive* live-lifecycle template: store the absolute + deadline on the grant row, recompute the verdict against `now()` on every + request, treat the periodic sweep as cleanup only. It also time-boxes + *denials*, not just grants. +- **Signet** (a fork of our own codebase) re-shipped our #24 bug — proof that + materializing a policy photocopy without a live join cannot enforce + grant-level TTL/usage. Its schema is still the best reference for the + token/policy decomposition (minus the one `applyToken` materialization line). +- **FROSTR** has the cleanest *revocation decomposition* (3 independent layers) + and a good auditable-credential table — but enforces **no** live expiry + anywhere. +- **promenade** confirms the **revoke = re-key** anti-pattern to avoid, and + debunks "FROST can't decrypt DMs" (it's a design choice, not a math limit). +- **NDK** (which we embed) is a deliberately *blank* permit seam: we own 100% of + policy — and `get_public_key` bypasses the seam entirely (see #26). + +Decision unchanged: **Option D, leaning D1.** Amber = live-evaluation reference; +Signet = schema reference; FROSTR = revocation-decomposition reference; NDK = +confirmed blank seam. + +## Strategic decision: keep our fork, treat Signet as a parts donor (2026-06-19) + +Signet is a fork/re-architecture of the same kind-0/nsecbunkerd lineage we +maintain, and is feature-richer on the standalone-operator surface (trust dial, +suspension, NIP-49 at-rest, two-tier tokens, kill-switch, React dashboard, +Android companion). We considered adopting it wholesale. **Decision: no — keep +our fork as what we ship; lift Signet's patterns as needed.** + +Why: +- **Replacing doesn't solve #25.** Signet re-ships our exact #24 (materialized + photocopy, no live grant-level join). We'd still have to do the live-join work + — after paying a migration cost. +- **We'd lose the integration that makes it ours.** LNbits wallet provisioning + (`usermanager` + nostdress), the OAuth-like `create_account` flow, and being + the signer target for the #18 `RemoteBunkerSigner` endgame. Porting those into + Signet just means maintaining a fork of a more opinionated upstream. +- **Lineage/bus-factor.** Our `master` tracks the canonical kind-0 upstream; + Signet is a solo-maintainer rewrite with choices we may not want (removed JWT + auth, Android surface). For a security-load-bearing component that's more risk, + not less. + +Why it's low-stakes either way: LNbits ↔ bunker is **NIP-46 over the wire** (the +deliberate protocol-over-IPC choice), so the signer is substitutable by design. +If our fork ever becomes a maintenance burden we can drop in any conformant +NIP-46 signer (Signet, Amber-as-bunker, HSM-backed) with config-only changes — +**not a one-way door.** + +Escape hatch (option 3, parked): run Signet unmodified behind the protocol. Only +attractive if the LNbits provisioning/OAuth flows move out of the bunker into +LNbits proper (plausible under #18), which would shrink the integration gap +that's the main reason to stay. Revisit if #25 implementation reveals our +daemon's NDK/relay/ACL plumbing is materially rougher than Signet's. + +--- + +## A — daemon/server implementations with a real policy model + +### Signet — `Letdown2491/signet` (TS daemon + React UI + Kotlin companion) +MIT, very active (v1.11.0, 2026-06). An extensive re-architecture of the same +kind-0/nsecbunkerd codebase we maintain. + +- **Re-ships our #24.** `applyToken` (`nip46-backend.ts:807`) checks + `Token.expiresAt` once at redeem (`:895`), then materializes `policy.rules` + into lifecycle-free `SigningCondition` rows (`:845-862`); the sign-time path + (`acl.ts:checkRequestPermission`) never reads `Token` again. + `maxUsageCount`/`currentUsageCount` are touched only in the policy CRUD route — + never enforced. Same materialization-drift bug as ours. +- **What it adds over us:** a coarse-cache layer for **subject-level** state on + `KeyUser` — `revokedAt`, `suspendedAt`/`suspendUntil`, `trustLevel` — read live + per request and invalidated on change (`invalidateAclCache`). Genuinely fixes + live *revoke* (our sibling spirekeeper#22). Puts revoke on **`KeyUser`, not + `Token`** — corroborating our revoke=subject / expiry=grant split. +- **Trust dial** over a kind-risk classifier: `trustLevel ∈ {paranoid, + reasonable, full}`, `SAFE_KINDS` auto / `SENSITIVE_KINDS` (0/3/4/5/wallet/ + auth/NIP-04) forced manual (`acl.ts:129-161`). +- **Two-tier tokens:** one-time `ConnectionToken` (mandatory `expiresAt`, + validates connect but never auto-approves) vs policy-backed `Token` (atomic + claim `updateMany where redeemedAt:null`, `nip46-backend.ts:813`). +- **Key-at-rest:** NIP-49 ncryptsec + AES-256-GCM envelope (PBKDF2-SHA256 @600k). +- **Takeaway:** adopt its `KeyUser` subject-state + `Request` indexing; reject + its `applyToken` materialization; the `ConnectionToken`-vs-`Token` split *is* + D1 in schema form. + +### Amber — `greenart7c3/Amber` (Android, Kotlin/Room) ⭐ live-lifecycle reference +MIT, very active (last commit 2026-06-19). Android signer (NIP-55 intents **and** +NIP-46 over relays). Listed in tier A despite being mobile because its permission +model is the strongest of any surveyed. + +- **Grant schema** (`ApplicationPermissionsEntity.kt:18-41`): unique composite + index over `(pkKey, type, kind, relay)` — per-(app × method × kind × relay). + Columns include `acceptable: Boolean`, `rememberType: Int`, `acceptUntil: + Long`, `rejectUntil: Long`. +- **Expiry enforced LIVE** (the key finding): `IntentUtils.isRemembered()` + (`IntentUtils.kt:1087-1101`) is the per-request verdict and recomputes + `acceptUntil > TimeUtils.now()` / `rejectUntil > now()` fresh every call; + expired → returns `null` → falls through to a user prompt. Called on both the + NIP-46 relay path (`EventNotificationConsumer.kt:440-441`) and the NIP-55 + intent path (`SignerProviderQuery.kt:183` etc.). +- **The sweep is non-load-bearing.** `updateExpiredPermissions(time)` + (`ApplicationDao.kt:51`, exempts `rememberType <> 4`=ALWAYS) runs every 24h via + WorkManager — pure cleanup; correctness doesn't depend on it firing because the + decision is recomputed against `now()` on read. +- **Time-boxed denials too:** `rejectUntil` means "reject for 5 min" decays back + to a prompt rather than a permanent no — a nicer primitive than a single + allow/deny flag. +- **Wildcard-as-distinct-tier:** lookup ladder is exact-kind → all-kinds + (`kind IS NULL`, `getPermissionAllKinds`, `ApplicationDao.kt:87-91`); relay + wildcard matches `'*' OR '' OR NULL` in one query (`getWildcardRelayPermission`, + `:101-106`). Wildcard rows are explicitly queried, never an accidental + missing-WHERE match. +- **Read-through LRU caches rows, not verdicts** (`CachingApplicationDao`) — keeps + the live `now()` re-check on every cache hit; invalidation is write-driven and + coarse per-app. +- **Sign policies** (`ChooseSignPolicy.kt:32-45`, stored as `signPolicy: Int`): + `0` basic / `1` manual-per-new-app / `2` fully-auto (short-circuits to allow + before any row lookup, `IntentUtils.kt:1090`). +- **Key-at-rest** (`SecureCryptoHelper.kt`): Android Keystore AES-256-GCM, 96-bit + IV / 128-bit tag, StrongBox-backed when available with TEE fallback and a + MediaTek denylist; optional app-level biometric gate. +- **NIP-46 coverage** (`SignerType.kt`, `BunkerRequestUtils.kt:232-248`): connect, + sign_event, nip04/nip44 (+v3) encrypt/decrypt, get_public_key, + decrypt_zap_event, ping, switch_relays, sign_psbt, logout; both `bunker://` and + `nostrconnect://`. +- **Steal for us:** absolute-deadline-on-row + recompute-vs-now per request; + time-boxed denials; wildcard as a distinct explicitly-queried tier; cache rows + not answers. + +### FROSTR — `FROSTR-ORG/igloo-server` + `bifrost` (TS, FROST k-of-n) +MIT. igloo-server v1.2.0 (2026-05-28); bifrost v2.0.2 (2026-01-24). Threshold +Schnorr over Nostr; igloo-server exposes the NIP-46 endpoint, bifrost is the node +SDK. + +- **Three independent authorization layers** (the prize): + 1. **App NIP-46 policy** — `Nip46Policy { methods?, kinds? }` (`db/nip46.ts:8-11`), + sessions keyed `(user_id, client_pubkey)` (`:92`), checked live per request + (`service.ts:508-509, 766-795`). No TTL/expiry. Session revoke is **explicit** + (`status='revoked'`, `:792-826`); per-method/kind revoke is **implicit** (flip + boolean false, audited at `:722-790`). + 2. **Peer-transport policy** — per-peer directional `allowSend`/`allowReceive` + (`util/peer-policy.ts:3-9`, `docs/PEER_POLICIES.md`), enforced in bifrost + `_filter`/`get_recv_pubkeys` (`client.ts:226-245`). **Correction:** it's + *default-allow + explicit per-peer deny + last-layer-wins*, not "deny-override". + 3. **Operator API auth** — keys stored SHA-256 hash+prefix with `revoked_at` + (checked first, timing-safe) + `last_used_at/ip` (`migrations/..._api_keys.sql`, + `database.ts:815-1047`); Argon2id password hashing (`config/crypto.ts:26-31`). +- **No layer enforces live expiry.** `nip46_requests.expires_at` exists but is + never populated; the only time-based enforcement is the in-memory derived-key + vault (TTL + bounded reads + zeroize, `auth.ts:359-459`). +- **Key-at-rest:** DB mode AES-256-GCM in SQLite, PBKDF2-HMAC-SHA256 **@600k** + (corrected from "~200k", `config/crypto.ts:7-11`); headless mode = plaintext env + (`GROUP_CRED`/`SHARE_CRED`). +- **Distributed veto** is real at the participation level (a co-signer withholding + its partial below threshold blocks the sig) but the default signer auto-signs + (`middleware: {}`, `client.ts:55`) — realizing a veto needs a custom + `middleware.sign` not shipped by default. +- **Share rotation** (recover → re-split, same group npub, old shares can't + combine) exists as a **bifrost SDK primitive** (`generate_dealer_package`), **not** + as an igloo-server endpoint; recovery reconstructs the full nsec in memory and + `/api/recover` even returns it over HTTP (`routes/recovery.ts:147-157`). +- **Steal for us:** the 3-layer revocation decomposition; audit-event-on-grant- + change; `revoked_at`-checked-first + last-used credential table. + +### promenade — fiatjaf (Go, FROST coordinator + signer split) +Off GitHub; cloned from fiatjaf's nostr-git (`relay.ngit.dev/npub180c…/promenade.git`), +HEAD `70ff8439` 2026-06-18. NIP-46 method logic lives in the pinned dep +`fiatjaf.com/nostr` (`nip46.DynamicSigner`). + +- **Architecture:** khatru coordinator-relay doubles as the NIP-46 endpoint, runs + the FROST ceremony, holds a transport/handler key but **no shard** + (`account_registration.go:44` carries only `frost.PublicKeyShard`); separate + signer daemons each hold one shard; m-of-n with m≤20 (`:79`). Signing-ceremony + kinds 26430–26434; account registration is kind **16430** (replaceable). +- **No encrypted DMs — by choice, not by math.** `DynamicSigner` recognizes + `nip44_encrypt`/`nip44_decrypt`/`switch_relays` (`dynamic-signer.go`), but + promenade hardwires `AuthorizeEncryption → false` (`coordinator/nip46.go:167`) + and `GroupContext.Encrypt/Decrypt → "not implemented"` (`sign.go:288-302`). + README: *"destroyer of encryption."* **Correction:** threshold ECDH is NOT + impossible for FROST — `frost/ecdh.go` implements `CreateECDHShare` / + `AggregateECDHShards`; it's simply not plumbed in. +- **ACL:** `AuthorizeSigning` per sign_event (`coordinator/nip46.go:86`); named + profiles `["profile", name, secret, restrictions]` where restrictions is a + `nostr.Filter` but only `Kinds` + `Until` are enforced (`:139-159`). The secret + is a reusable bearer capability. +- **Lifecycle:** per-profile `Until` is the only time-bound; **no revoke API** — + dropping one capability means re-publishing the whole kind:16430 account signed + by the **master nsec**. The **revoke = re-key anti-pattern** to avoid. +- **Key-at-rest:** nsec sharded client-side (never whole), but shards stored + **plaintext** in each signer's BoltDB (`acceptor.go:209`); coordinator/signer + identity keys from plaintext env. +- **Relevance:** confirms (1) keep grant-revoke independent of key rotation, and + (2) for the #18 "bunker for everything" endgame, threshold-protecting the server + identity wouldn't *mathematically* preclude DM decryption — but keeping ECDH on a + separate non-threshold key is the cheaper path. + +--- + +## B — library/SDK signer seams + +### NDK — `nostr-dev-kit/ndk` (we embed this) @ `4b86acd` (2026-04-05) +nip46 under `core/src/signers/nip46/`. + +- Backend `NDKNip46Backend` (`backend/index.ts:58`), client `NDKNip46Signer` + (`index.ts:60`). +- Permit seam: `Nip46PermitCallback = (params: {id, pubkey, method, params?}) => + Promise` (`backend/index.ts:29-43`), invoked via overridable + `pubkeyAllowed()` (`:229-231`) from each strategy. +- **`get_public_key` bypasses the seam** — `backend/get-public-key.ts:3-11` + returns the pubkey with no `pubkeyAllowed` call. (rust-nostr's `approve()` wraps + every method including this one.) See #26. +- Signature verified before dispatch (`index.ts:181`); strategies swappable + (`setStrategy`, `:156-158`). +- `applyToken(pubkey, token)` default-throws (`:166-168`), invoked by the connect + handler when a token is present (`connect.ts:21-24`) — token policy is the + embedder's job. +- **No** built-in scoping/kinds/rate-limit/expiry/persistence — all policy lives + behind the one callback. We own 100% of the policy engine. + +### rust-nostr / nostr-sdk @ `e47b572` (v0.45.0-alpha.1) +- `NostrConnectRemoteSigner` (`signer.rs:39`) + `NostrConnect` client. +- Trait `NostrConnectSignerActions::approve(&self, public_key, req) -> bool` + (`signer.rs:342-345`), synchronous bool, wraps the **entire** request match in + `serve()` (`:201-202`) — gates every method **including** `get_public_key`. +- FFI (uniffi/wasm) exposes **only the client** `NostrConnect`, not the backend — + no non-Rust embedding of the signer side. + +### nak — `fiatjaf/nak` bunker subcommand @ `483bf94` +- Allow-list of client pubkeys (`BunkerConfig.Clients`), `--persist`s 0600 JSON. +- Once authorized, **signs everything** — no method/kind scoping, no expiry, no + rate limiting. Notably its underlying lib computes a `harmless` (connect/ + get_public_key/ping) vs dangerous (sign/encrypt/decrypt) hint that nak + **discards**. A bare always-sign baseline. + +--- + +## C — clients / extensions (less relevant; novel UX only) + +- **keys.band** — Svelte Chrome extension (NIP-07): the one browser signer with + *time-bounded* authorization grants (allow-for-N-minutes/session). Relevant to a + TTL-grant UX. +- **nos2x / nos2x-fox** (fiatjaf) — origin of the per-origin "remember / allow + this site" NIP-07 model; key stored ~plaintext in extension storage. +- **Gossip** (Rust desktop) — not a bunker, but best-in-class key-at-rest: + passphrase-encrypted on disk, startup unlock, memory zeroed before free. Clean + `LocalSigner` envelope reference. +- **Primal**, **nowser** (Flutter) — clients that also serve NIP-46/NIP-55; use the + standard `optional_requested_perms` per-method/per-kind grammar. + +--- + +## D — not bunkers / dead + +- **`Letdown2491/nip46-relay`** — a NIP-46 *transport relay* (forwards opaque + blobs), no signing/authz. Appears next to Signet; easy to mistake for a signer. +- **Keychat** — Signal-over-Nostr chat app; signs only its own events. +- **python-nostr** — abandoned 2022, no NIP-46. (No Python library offers a + signer-side permission abstraction; a Python bunker means hand-rolling the + kind-24133 loop or driving rust-nostr via FFI — and the FFI exposes only the + client.) + +--- + +## Patterns worth stealing — consolidated + +1. **Live evaluation (Amber):** absolute deadline on the grant row; verdict is a + pure function recomputed vs `now()` per request; sweep is cleanup-only. This is + Option D, proven in production. +2. **Time-box denials too (Amber `rejectUntil`):** a deny decays to a prompt. +3. **Wildcard as a distinct, explicitly-queried tier (Amber):** never a fuzzy + missing-WHERE match in the auto-decide path. +4. **Cache rows, never verdicts (Amber `CachingApplicationDao`, Signet coarse + cache):** keep the `now()` re-check on every hit; invalidate on write. +5. **Subject vs grant separation (Signet):** revoke/suspend/trust on `KeyUser` + (cheap, cache+invalidate); expiry/usage on `Token`/`Policy` (must join live). +6. **Usage = COUNT(Request) in window (lnbits/nostr_bunker), not a mutable + counter:** drop `currentUsageCount`; needs `Request.keyUserId` + index. +7. **Revocation decomposition (FROSTR):** app-grant revoke ≠ transport quarantine ≠ + key rotation. Never collapse grant-revoke into re-key (promenade anti-pattern). +8. **Auditable, revocable credentials (FROSTR):** `revoked_at` checked first + + last-used tracking; audit-event-on-grant-change decoupled from enforcement. +9. **Single predicate `grantIsLive(now)`** used at both redeem and sign time + (the discipline that prevents the original drift). +10. **NDK seam reality:** we own all policy; design around `get_public_key` + bypassing `pubkeyAllowed`. From 6397c7988dcca21464cb505673d435177194ab03 Mon Sep 17 00:00:00 2001 From: Padreug Date: Fri, 19 Jun 2026 15:00:33 +0200 Subject: [PATCH 31/36] feat(schema)(#25): Request.keyUserId + SigningCondition lifecycle for live grant eval Additive, non-breaking schema prep for the Option D live-evaluation ACL: - Request gains keyUserId (FK) + @@index([keyUserId, method]) so token usage caps can be derived live by COUNTing allowed Requests, replacing the never-enforced mutable PolicyRule.currentUsageCount (derive-don't-count, per lnbits/nostr_bunker prior art). - SigningCondition gains createdAt/expiresAt/revokedAt so the manual-override layer carries its own lifecycle and runs through the same grantIsLive(now) predicate as token grants (D1: two typed sources, one shared rule). No behavior change yet; the ACL hot path and applyToken de-materialization follow in subsequent commits. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../migration.sql | 37 +++++++++++++++++++ prisma/schema.prisma | 23 +++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 prisma/migrations/20260619125847_live_grant_lifecycle_schema/migration.sql diff --git a/prisma/migrations/20260619125847_live_grant_lifecycle_schema/migration.sql b/prisma/migrations/20260619125847_live_grant_lifecycle_schema/migration.sql new file mode 100644 index 0000000..7608e6e --- /dev/null +++ b/prisma/migrations/20260619125847_live_grant_lifecycle_schema/migration.sql @@ -0,0 +1,37 @@ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_Request" ( + "id" TEXT NOT NULL PRIMARY KEY, + "keyName" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "requestId" TEXT NOT NULL, + "remotePubkey" TEXT NOT NULL, + "method" TEXT NOT NULL, + "params" TEXT, + "allowed" BOOLEAN, + "keyUserId" INTEGER, + CONSTRAINT "Request_keyUserId_fkey" FOREIGN KEY ("keyUserId") REFERENCES "KeyUser" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); +INSERT INTO "new_Request" ("allowed", "createdAt", "id", "keyName", "method", "params", "remotePubkey", "requestId") SELECT "allowed", "createdAt", "id", "keyName", "method", "params", "remotePubkey", "requestId" FROM "Request"; +DROP TABLE "Request"; +ALTER TABLE "new_Request" RENAME TO "Request"; +CREATE INDEX "Request_keyUserId_method_idx" ON "Request"("keyUserId", "method"); +CREATE TABLE "new_SigningCondition" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "method" TEXT, + "kind" TEXT, + "content" TEXT, + "keyUserKeyName" TEXT, + "allowed" BOOLEAN, + "keyUserId" INTEGER, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "expiresAt" DATETIME, + "revokedAt" DATETIME, + CONSTRAINT "SigningCondition_keyUserId_fkey" FOREIGN KEY ("keyUserId") REFERENCES "KeyUser" ("id") ON DELETE SET NULL ON UPDATE CASCADE +); +INSERT INTO "new_SigningCondition" ("allowed", "content", "id", "keyUserId", "keyUserKeyName", "kind", "method") SELECT "allowed", "content", "id", "keyUserId", "keyUserKeyName", "kind", "method" FROM "SigningCondition"; +DROP TABLE "SigningCondition"; +ALTER TABLE "new_SigningCondition" RENAME TO "SigningCondition"; +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f0072ea..73f54df 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -17,6 +17,14 @@ model Request { method String params String? allowed Boolean? + // Bind each request to the KeyUser it was evaluated against so usage + // caps can be derived live by COUNTing allowed Requests, instead of + // maintaining a mutable PolicyRule.currentUsageCount that drifts. + // See aiolabs/nsecbunkerd#25 (Option D, derive-don't-count). + keyUserId Int? + KeyUser KeyUser? @relation(fields: [keyUserId], references: [id]) + + @@index([keyUserId, method]) } model KeyUser { @@ -31,6 +39,7 @@ model KeyUser { logs Log[] signingConditions SigningCondition[] Token Token[] + requests Request[] @@unique([keyName, userPubkey], name: "unique_key_user") } @@ -56,15 +65,25 @@ model User { pubkey String } +// The SigningCondition layer is the MANUAL-OVERRIDE source of truth +// (web-approval / add_signing_condition / create_account bootstrap) — it is +// no longer materialized from token policies (see aiolabs/nsecbunkerd#25: +// applyToken stopped photocopying; token grants are evaluated live off +// Token -> Policy -> PolicyRule). Under D1 the override layer carries its +// own lifecycle so it runs through the same grantIsLive(now) predicate as +// token grants. model SigningCondition { - id Int @id @default(autoincrement()) + id Int @id @default(autoincrement()) method String? kind String? content String? keyUserKeyName String? allowed Boolean? keyUserId Int? - KeyUser KeyUser? @relation(fields: [keyUserId], references: [id]) + createdAt DateTime @default(now()) + expiresAt DateTime? + revokedAt DateTime? + KeyUser KeyUser? @relation(fields: [keyUserId], references: [id]) } model Log { From 85e781dfa9836ff448514b8c7bb350dc4b46a87e Mon Sep 17 00:00:00 2001 From: Padreug Date: Fri, 19 Jun 2026 15:11:23 +0200 Subject: [PATCH 32/36] fix(acl)(#24,#25): enforce token expiry+revoke live at sign time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bug (#24): applyToken photocopied a token's policy rules into SigningCondition rows at redeem; checkIfPubkeyAllowed matched those rows (step 3) and short-circuited before the live Token join (step 4), so an expired or revoked token kept signing forever — the copy carried no lifecycle. Same cause re-shipped by upstream Signet (see docs survey). Option D fix: - grantIsLive(grant, now): the single 'valid right now?' predicate (revokedAt null AND not past expiresAt), used identically at redeem (Backend.validateToken) and sign (checkIfPubkeyAllowed). Redeem and sign can no longer disagree. - Backend.applyToken records ONLY the KeyUser<-Token binding; it no longer materializes SigningCondition rows. Token policy is evaluated live every request. - checkIfPubkeyAllowed step 4 filters tokens through liveWhere(now) (revoke + expiry) and grants connect off a live bound token; the manual-override layer (step 3) now honors SigningCondition expiresAt/revokedAt too (denials beat grants). Closes the materialization-drift family: a new lifecycle rule is one more predicate, never a forgotten photocopy. Token-revoke sibling (spirekeeper#22) falls out of the same seam. Usage caps deferred (no durable signing log exists yet to count) — follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/daemon/backend/index.ts | 41 +++----- src/daemon/lib/acl/index.ts | 192 +++++++++++++++++++++++------------- 2 files changed, 136 insertions(+), 97 deletions(-) diff --git a/src/daemon/backend/index.ts b/src/daemon/backend/index.ts index 5d05a8a..91f2f58 100644 --- a/src/daemon/backend/index.ts +++ b/src/daemon/backend/index.ts @@ -1,6 +1,7 @@ import NDK, { NDKNip46Backend, NDKPrivateKeySigner, Nip46PermitCallback } from '@nostr-dev-kit/ndk'; import prisma from '../../db.js'; import type {FastifyInstance} from "fastify"; +import { grantIsLive } from '../lib/acl/index.js'; export class Backend extends NDKNip46Backend { public baseUrl?: string; @@ -91,7 +92,10 @@ export class Backend extends NDKNip46Backend { if (!tokenRecord) throw new Error("Token not found"); if (tokenRecord.redeemedAt) throw new Error("Token already redeemed"); if (!tokenRecord.policy) throw new Error("Policy not found"); - if (tokenRecord.expiresAt && tokenRecord.expiresAt < new Date()) throw new Error("Token expired"); + // Revoke + expiry via the single grantIsLive predicate — the exact + // check the sign-time ACL uses, so redeem-time and sign-time cannot + // drift (the root of #24). See aiolabs/nsecbunkerd#25. + if (!grantIsLive(tokenRecord)) throw new Error("Token expired or revoked"); return tokenRecord; } @@ -100,39 +104,20 @@ export class Backend extends NDKNip46Backend { const tokenRecord = await this.validateToken(token); const keyName = tokenRecord.keyName; - // Upsert the KeyUser with the given remotePubkey + // Record ONLY the binding (KeyUser <- Token). Under #25 the token's + // policy is evaluated live at sign time (checkIfPubkeyAllowed step 4) + // off Token -> Policy -> PolicyRule, NOT photocopied into + // SigningCondition rows here. That photocopy was the root of #24: the + // copy carried no expiry/revoke and short-circuited the live check, so + // an expired or revoked token kept signing forever. With no copy, the + // token's lifecycle is re-checked on every request and there is nothing + // to keep in sync. const upsertedUser = await prisma.keyUser.upsert({ where: { unique_key_user: { keyName, userPubkey } }, update: { }, create: { keyName, userPubkey, description: tokenRecord.clientName }, }); - await prisma.signingCondition.create({ - data: { - keyUserId: upsertedUser.id, - method: 'connect', - allowed: true, - } - }); - - // Go through the rules of this policy and apply them to the user - for (const rule of tokenRecord!.policy!.rules) { - const signingConditionQuery: any = { method: rule.method }; - - if (rule && rule.kind) { - signingConditionQuery.kind = rule.kind.toString(); - } - - await prisma.signingCondition.create({ - data: { - keyUserId: upsertedUser.id, - method: rule.method, - allowed: true, - ...signingConditionQuery, - } - }); - } - await prisma.token.update({ where: { id: tokenRecord.id }, data: { diff --git a/src/daemon/lib/acl/index.ts b/src/daemon/lib/acl/index.ts index f621c98..a3f17ab 100644 --- a/src/daemon/lib/acl/index.ts +++ b/src/daemon/lib/acl/index.ts @@ -1,31 +1,71 @@ -import { NDKEvent, NostrEvent, NIP46Method } from '@nostr-dev-kit/ndk'; +import { NostrEvent, NIP46Method } from '@nostr-dev-kit/ndk'; import prisma from '../../../db.js'; /** - * Layered authorization check. Order matters: + * "Is this grant valid right now?" — the single lifecycle predicate, used + * identically at redeem time (Backend.validateToken) and sign time + * (checkIfPubkeyAllowed). Both Token and SigningCondition carry `revokedAt` + * + `expiresAt`, so one shape governs token grants and manual overrides. + * + * The original #24 bug was possible because redeem-time checked expiry and + * sign-time didn't — two definitions of "valid" that drifted. Defining it + * once makes them impossible to disagree. See aiolabs/nsecbunkerd#25. + */ +export function grantIsLive( + grant: { revokedAt?: Date | null; expiresAt?: Date | null }, + now: Date = new Date(), +): boolean { + if (grant.revokedAt) return false; + if (grant.expiresAt && grant.expiresAt.getTime() <= now.getTime()) return false; + return true; +} + +/** + * Prisma `where` fragment selecting only lifecycle-live rows (not revoked, + * not past expiry) — grantIsLive expressed in SQL so the live filter happens + * in the query, not in app code after the fact. `now` is threaded in so a + * single request evaluates every row against one clock reading. + */ +function liveWhere(now: Date) { + return { + revokedAt: null, + OR: [{ expiresAt: null }, { expiresAt: { gt: now } }], + }; +} + +/** + * Layered authorization check. Order matters (denials beat grants): * * 1. fetch KeyUser; if missing → undefined (no binding exists) - * 2. if KeyUser.revokedAt set → false (binary user revoke beats everything) - * 3. SigningCondition override layer (per-user grants/denies): - * - explicit reject (method='*', allowed=false) → false - * - matching per-(method,kind) row → return row.allowed - * 4. Live policy join over KeyUser → Token → Policy → PolicyRule - * with Token.revokedAt IS NULL and a matching rule → true - * 5. else → undefined (denied) + * 2. KeyUser.revokedAt set → false (subject-level ban beats everything) + * 3. manual-override layer (LIVE SigningConditions only): + * - live explicit reject (method='*', allowed=false) → false + * - live matching per-(method,kind) deny → false + * - live matching per-(method,kind) grant → true + * 4. live token grant: a redeemed Token bound to this KeyUser that is + * neither revoked nor expired pairs the user (`connect`) outright and, + * via its policy, governs signing. Token expiry/revoke are evaluated + * HERE, every request — not photocopied at redeem (#24). + * 5. else → undefined (caller's requestPermission flow may prompt an admin) * - * Step 3 must precede step 4: per-user denies override the policy, and - * per-user grants extend beyond the policy. Step 2 must precede step 3: - * a revoked KeyUser stays revoked regardless of conditions or policy. + * Unlike the pre-#25 algorithm, token grants are no longer materialized into + * SigningCondition rows at redeem (Backend.applyToken stopped photocopying), + * so step 4 is the live source of truth for token lifecycle. The override + * layer (step 3) is manual-only and now carries its own lifecycle, so an + * expired/revoked override stops granting too. * - * See aiolabs/nsecbunkerd#11 and the issue comment that ratified the - * algorithm (https://git.atitlan.io/aiolabs/nsecbunkerd/issues/11#issuecomment-1473). + * Supersedes the #11 algorithm; closes the materialization-drift family + * behind #24. See aiolabs/nsecbunkerd#25. */ export async function checkIfPubkeyAllowed( keyName: string, remotePubkey: string, method: IMethod, - payload?: string | NostrEvent + payload?: string | NostrEvent, ): Promise { + // One clock reading for the whole decision. + const now = new Date(); + // Step 1: find KeyUser. const keyUser = await prisma.keyUser.findUnique({ where: { unique_key_user: { keyName, userPubkey: remotePubkey } }, @@ -35,81 +75,95 @@ export async function checkIfPubkeyAllowed( return undefined; } - // Step 2: binary user revoke. + // Step 2: subject-level revoke (sticky ban, beats everything). if (keyUser.revokedAt) { return false; } - // Step 3a: explicit-reject override (rejectAllRequestsFromKey writes this). + const live = liveWhere(now); + + // Step 3a: live explicit reject. const explicitReject = await prisma.signingCondition.findFirst({ - where: { - keyUserId: keyUser.id, - method: '*', - allowed: false, - } + where: { keyUserId: keyUser.id, method: '*', allowed: false, ...live }, }); if (explicitReject) { - console.log(`explicit reject`, explicitReject); return false; } - // Step 3b: matching per-(method, kind) override. + // Step 3b: live matching per-(method, kind) override — deny beats grant. const signingConditionQuery = requestToSigningConditionQuery(method, payload); - const signingCondition = await prisma.signingCondition.findFirst({ - where: { - keyUserId: keyUser.id, - ...signingConditionQuery, - } + const liveDeny = await prisma.signingCondition.findFirst({ + where: { keyUserId: keyUser.id, ...signingConditionQuery, allowed: false, ...live }, }); - if (signingCondition && (signingCondition.allowed === true || signingCondition.allowed === false)) { - console.log(`found signing condition`, signingCondition); - return signingCondition.allowed; + if (liveDeny) { + return false; } - // Step 4: live policy join. Walk every non-revoked Token bound to this - // KeyUser; if any of their policies has a matching PolicyRule, allow. - // - // PolicyRule.kind matching: - // - exact match against payload kind (stringified — matches the - // create_new_policy.ts:23 storage format `rule.kind.toString()`) - // - 'all' literal matches any kind (parity with the override-layer - // allowScopeToSigningConditionQuery convention) - // - NULL kind is a defensive branch — no current code path inserts - // PolicyRules with null kind, but if one ever appears (raw SQL, - // future code, schema migration) we treat it as a wildcard rather - // than failing closed silently. - const payloadKindString = (method === 'sign_event' && typeof payload === 'object' && payload?.kind !== undefined) - ? payload.kind.toString() - : undefined; - - const kindMatchers: Array<{ kind: string | null }> = [{ kind: null }, { kind: 'all' }]; - if (payloadKindString !== undefined) { - kindMatchers.push({ kind: payloadKindString }); - } - - const policyAllowance = await prisma.token.findFirst({ - where: { - keyUserId: keyUser.id, - revokedAt: null, - policy: { - rules: { - some: { - method, - OR: kindMatchers, - }, - }, - }, - }, + const liveGrant = await prisma.signingCondition.findFirst({ + where: { keyUserId: keyUser.id, ...signingConditionQuery, allowed: true, ...live }, }); - if (policyAllowance) { + if (liveGrant) { return true; } - // Step 5: no override granted, no policy rule matched. Caller's + // Step 4: live token grant. + // + // A redeemed token that is live (not revoked, not past expiry) grants + // `connect` (the pairing) outright, and grants other methods when its + // policy has a matching PolicyRule. The live filter is what closes #24: + // an expired or revoked token simply stops matching here, every request, + // with no photocopy to outlive it. + if (method === 'connect') { + const liveToken = await prisma.token.findFirst({ + where: { keyUserId: keyUser.id, ...live }, + }); + + if (liveToken) { + return true; + } + } else { + // PolicyRule.kind matching: + // - exact match against the stringified payload kind (matches the + // create_new_policy.ts storage format `rule.kind.toString()`) + // - 'all' literal matches any kind + // - NULL kind is a defensive wildcard — no current writer emits a + // null-kind rule, but treat it as a wildcard rather than failing + // closed silently if one ever appears (raw SQL, future code). + const payloadKindString = + method === 'sign_event' && typeof payload === 'object' && payload?.kind !== undefined + ? payload.kind.toString() + : undefined; + + const kindMatchers: Array<{ kind: string | null }> = [{ kind: null }, { kind: 'all' }]; + if (payloadKindString !== undefined) { + kindMatchers.push({ kind: payloadKindString }); + } + + const policyAllowance = await prisma.token.findFirst({ + where: { + keyUserId: keyUser.id, + ...live, + policy: { + rules: { + some: { + method, + OR: kindMatchers, + }, + }, + }, + }, + }); + + if (policyAllowance) { + return true; + } + } + + // Step 5: no live override and no live token grant matched. Caller's // requestPermission flow may still prompt the admin out-of-band. return undefined; } @@ -211,4 +265,4 @@ export async function rejectAllRequestsFromKey(remotePubkey: string, keyName: st keyUserId: upsertedUser.id, }, }); -} \ No newline at end of file +} From e2cf10a66de8381ddc88fdd533ace61716fcd764 Mon Sep 17 00:00:00 2001 From: Padreug Date: Fri, 19 Jun 2026 15:16:37 +0200 Subject: [PATCH 33/36] test(acl)(#25): extract pure grantIsLive/liveWhere + unit tests Move the lifecycle predicate into lib/acl/lifecycle.ts (re-exported from the ACL module) so it can be unit-tested without a database. Adds Node built-in test-runner coverage for the boundary conditions that define the fix: past expiry -> dead, expiry == now -> dead (exclusive), revoke beats a future expiry, and liveWhere kept in lockstep with grantIsLive. Runner is node:test via ts-node (no new dependency; pnpm add is blocked by the nix-built node_modules hoist pattern). 'npm test' -> 7 passing. Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 1 + src/daemon/lib/acl/index.ts | 36 ++++----------------------- src/daemon/lib/acl/lifecycle.ts | 40 ++++++++++++++++++++++++++++++ tests/lifecycle.test.ts | 44 +++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 31 deletions(-) create mode 100644 src/daemon/lib/acl/lifecycle.ts create mode 100644 tests/lifecycle.test.ts diff --git a/package.json b/package.json index 4975b68..f1f8732 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "scripts": { "build": "tsup src/index.ts; tsup src/daemon/index.ts -d dist/daemon; tsup src/client.ts -d dist/client", "build:client": "tsup src/client.ts -d dist/client", + "test": "TS_NODE_TRANSPILE_ONLY=1 node -r ts-node/register --test tests/*.test.ts", "prisma:generate": "npx prisma generate", "prisma:migrate": "npx prisma migrate deploy", "prisma:create": "npx prisma db push --preview-feature", diff --git a/src/daemon/lib/acl/index.ts b/src/daemon/lib/acl/index.ts index a3f17ab..d693e72 100644 --- a/src/daemon/lib/acl/index.ts +++ b/src/daemon/lib/acl/index.ts @@ -1,37 +1,11 @@ import { NostrEvent, NIP46Method } from '@nostr-dev-kit/ndk'; import prisma from '../../../db.js'; +import { liveWhere } from './lifecycle.js'; -/** - * "Is this grant valid right now?" — the single lifecycle predicate, used - * identically at redeem time (Backend.validateToken) and sign time - * (checkIfPubkeyAllowed). Both Token and SigningCondition carry `revokedAt` - * + `expiresAt`, so one shape governs token grants and manual overrides. - * - * The original #24 bug was possible because redeem-time checked expiry and - * sign-time didn't — two definitions of "valid" that drifted. Defining it - * once makes them impossible to disagree. See aiolabs/nsecbunkerd#25. - */ -export function grantIsLive( - grant: { revokedAt?: Date | null; expiresAt?: Date | null }, - now: Date = new Date(), -): boolean { - if (grant.revokedAt) return false; - if (grant.expiresAt && grant.expiresAt.getTime() <= now.getTime()) return false; - return true; -} - -/** - * Prisma `where` fragment selecting only lifecycle-live rows (not revoked, - * not past expiry) — grantIsLive expressed in SQL so the live filter happens - * in the query, not in app code after the fact. `now` is threaded in so a - * single request evaluates every row against one clock reading. - */ -function liveWhere(now: Date) { - return { - revokedAt: null, - OR: [{ expiresAt: null }, { expiresAt: { gt: now } }], - }; -} +// Re-export the single lifecycle predicate so callers (e.g. +// Backend.validateToken) import it from the ACL module. The implementation +// lives in ./lifecycle.ts so it can be unit-tested without a database. +export { grantIsLive } from './lifecycle.js'; /** * Layered authorization check. Order matters (denials beat grants): diff --git a/src/daemon/lib/acl/lifecycle.ts b/src/daemon/lib/acl/lifecycle.ts new file mode 100644 index 0000000..783dd84 --- /dev/null +++ b/src/daemon/lib/acl/lifecycle.ts @@ -0,0 +1,40 @@ +/** + * Pure grant-lifecycle logic, extracted from the ACL so it can be unit-tested + * without a database and reused verbatim at redeem time and sign time. + * + * The original #24 bug was possible because redeem-time checked expiry and + * sign-time didn't — two definitions of "valid" that drifted. Defining "is + * this grant valid right now?" exactly once makes them impossible to disagree. + * See aiolabs/nsecbunkerd#25. + */ + +/** The lifecycle fields every grant (Token, SigningCondition) carries. */ +export type Lifecycle = { + revokedAt?: Date | null; + expiresAt?: Date | null; +}; + +/** + * "Is this grant valid right now?" — the single lifecycle predicate. A grant + * is live iff it has not been revoked and its expiry (if any) is still in the + * future. Expiry is treated as exclusive at the boundary: a grant whose + * `expiresAt` equals `now` is already dead. + */ +export function grantIsLive(grant: Lifecycle, now: Date = new Date()): boolean { + if (grant.revokedAt) return false; + if (grant.expiresAt && grant.expiresAt.getTime() <= now.getTime()) return false; + return true; +} + +/** + * `grantIsLive` expressed as a Prisma `where` fragment, so the live filter + * runs in the query rather than in app code after the fetch. `now` is threaded + * in explicitly so a single request evaluates every row against one clock + * reading. Kept in lockstep with `grantIsLive` (see lifecycle.test.ts). + */ +export function liveWhere(now: Date) { + return { + revokedAt: null, + OR: [{ expiresAt: null }, { expiresAt: { gt: now } }], + }; +} diff --git a/tests/lifecycle.test.ts b/tests/lifecycle.test.ts new file mode 100644 index 0000000..4bbe5f1 --- /dev/null +++ b/tests/lifecycle.test.ts @@ -0,0 +1,44 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { grantIsLive, liveWhere } from '../src/daemon/lib/acl/lifecycle'; + +// Fixed reference clock so the assertions don't depend on wall time. +const now = new Date('2026-06-19T12:00:00.000Z'); +const past = new Date(now.getTime() - 60_000); +const future = new Date(now.getTime() + 60_000); + +test('grantIsLive: no revoke, no expiry -> live', () => { + assert.equal(grantIsLive({}, now), true); + assert.equal(grantIsLive({ revokedAt: null, expiresAt: null }, now), true); +}); + +test('grantIsLive: future expiry -> live', () => { + assert.equal(grantIsLive({ expiresAt: future }, now), true); +}); + +test('grantIsLive: past expiry -> dead (the #24 case the old code missed at sign time)', () => { + assert.equal(grantIsLive({ expiresAt: past }, now), false); +}); + +test('grantIsLive: expiry exactly now -> dead (boundary is exclusive)', () => { + assert.equal(grantIsLive({ expiresAt: new Date(now.getTime()) }, now), false); +}); + +test('grantIsLive: revoked -> dead even with a future expiry (revoke wins)', () => { + assert.equal(grantIsLive({ revokedAt: past, expiresAt: future }, now), false); +}); + +test('grantIsLive: defaults now to the current time', () => { + assert.equal(grantIsLive({ expiresAt: new Date(Date.now() + 3_600_000) }), true); + assert.equal(grantIsLive({ expiresAt: new Date(Date.now() - 3_600_000) }), false); +}); + +// liveWhere is the SQL mirror of grantIsLive; pin its shape so the two +// can't silently drift (a drift would re-open the redeem-vs-sign gap #25 +// exists to close). +test('liveWhere: mirrors grantIsLive as a prisma where-fragment', () => { + assert.deepEqual(liveWhere(now), { + revokedAt: null, + OR: [{ expiresAt: null }, { expiresAt: { gt: now } }], + }); +}); From 7dcf97a2966c6bb43f23def3339dab3d2df93548 Mon Sep 17 00:00:00 2001 From: Padreug Date: Fri, 19 Jun 2026 16:02:13 +0200 Subject: [PATCH 34/36] refactor(acl)(#27 review): remove dead reject-all sentinel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #27 review finding #3: step 3a queried SigningCondition method='*' and the docstring attributed it to rejectAllRequestsFromKey — but that function writes method=null (never '*') and has zero callers, so the 'reject all' branch could never match. Subject-level reject is already KeyUser.revokedAt (step 2, via the revoke_user admin command). Drop the dead step-3a branch and the orphaned rejectAllRequestsFromKey so the code matches reality. Per-(method,kind) denies (step 3, written by add_signing_condition) are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/daemon/lib/acl/index.ts | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/src/daemon/lib/acl/index.ts b/src/daemon/lib/acl/index.ts index d693e72..1c7912d 100644 --- a/src/daemon/lib/acl/index.ts +++ b/src/daemon/lib/acl/index.ts @@ -13,7 +13,6 @@ export { grantIsLive } from './lifecycle.js'; * 1. fetch KeyUser; if missing → undefined (no binding exists) * 2. KeyUser.revokedAt set → false (subject-level ban beats everything) * 3. manual-override layer (LIVE SigningConditions only): - * - live explicit reject (method='*', allowed=false) → false * - live matching per-(method,kind) deny → false * - live matching per-(method,kind) grant → true * 4. live token grant: a redeemed Token bound to this KeyUser that is @@ -56,16 +55,10 @@ export async function checkIfPubkeyAllowed( const live = liveWhere(now); - // Step 3a: live explicit reject. - const explicitReject = await prisma.signingCondition.findFirst({ - where: { keyUserId: keyUser.id, method: '*', allowed: false, ...live }, - }); - - if (explicitReject) { - return false; - } - - // Step 3b: live matching per-(method, kind) override — deny beats grant. + // Step 3: live matching per-(method, kind) override — deny beats grant. + // (Subject-level "reject all from this user" is KeyUser.revokedAt, applied + // at step 2 via the revoke_user admin command. There is no method='*' + // SigningCondition sentinel — nothing writes one.) const signingConditionQuery = requestToSigningConditionQuery(method, payload); const liveDeny = await prisma.signingCondition.findFirst({ @@ -223,20 +216,3 @@ export async function allowAllRequestsFromKey( console.log('allowAllRequestsFromKey', e); } } - -export async function rejectAllRequestsFromKey(remotePubkey: string, keyName: string): Promise { - // Upsert the KeyUser with the given remotePubkey - const upsertedUser = await prisma.keyUser.upsert({ - where: { unique_key_user: { keyName, userPubkey: remotePubkey } }, - update: { }, - create: { keyName, userPubkey: remotePubkey }, - }); - - // Create a new SigningCondition for the given KeyUser and set allowed to false - await prisma.signingCondition.create({ - data: { - allowed: false, - keyUserId: upsertedUser.id, - }, - }); -} From 14e20d50d47adec8ff80c823ea3f7302842764ed Mon Sep 17 00:00:00 2001 From: Padreug Date: Fri, 19 Jun 2026 22:58:12 +0200 Subject: [PATCH 35/36] docs: add migration & DB-maintenance runbook (never full-wipe nsecbunker.db) Captures the deploy hazard found during #27 rollout (cfaun): the nsecbunkerd<->LNbits pairing is split across both systems, so a full nsecbunker.db wipe orphans LNbits's signer_config and forces an identity-changing re-provision. Documents the targeted 'DELETE FROM SigningCondition' procedure, the keys-live-in-json fact, and the migrate-on-boot no-op (#31). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/runbook-migrations.md | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 docs/runbook-migrations.md diff --git a/docs/runbook-migrations.md b/docs/runbook-migrations.md new file mode 100644 index 0000000..9c1dcac --- /dev/null +++ b/docs/runbook-migrations.md @@ -0,0 +1,65 @@ +# nsecbunkerd migration & DB-maintenance runbook + +Operational notes for applying schema migrations and ACL/pairing maintenance on +deployed, **LNbits-connected** nsecbunkerd instances. + +## ⚠️ Never full-wipe `nsecbunker.db` on an LNbits-connected instance + +The nsecbunkerd ↔ LNbits pairing is **split across both systems**: + +- **Bunker** (`nsecbunker.db`): per-account `KeyUser` binding (keyed by LNbits's + stable client pubkey) + redeemed `Token` + a shared `Policy`. +- **LNbits** (`accounts.signer_config`, `RemoteBunkerSigner`): + `{token, client_nsec, policy_id}`. + +`RemoteBunkerSigner.sign_event()` signs **directly with the stored `client_nsec`** +— it does NOT re-connect/re-redeem, and there is **no auto-repair** on restart or +sign-failure. `provision()` runs only at new-account creation and mints a NEW +npub (which changes the user's nostr identity). + +**Consequence of a full `nsecbunker.db` wipe:** the `KeyUser` bindings are +deleted → every LNbits account's stored config dangles → all signing fails, and +the only standard "repair" (`provision()`) changes identities. **Do not do it.** + +### Correct way to strip the #24 materialized photocopies + +Post-#27, token grants are evaluated live via the ACL step-4 `Token → Policy → +PolicyRule` join, so the old materialized `SigningCondition` rows are redundant +— and, written with `expiresAt = NULL`, they would keep granting past a token's +expiry (silently re-opening #24 for already-paired clients). Strip them with a +**targeted delete** that preserves the pairing: + +```sql +-- Verify first. +SELECT COUNT(*) FROM Token WHERE redeemedAt IS NOT NULL; -- bindings to preserve +SELECT COUNT(*) FROM SigningCondition; -- photocopies to strip + +-- Keeps KeyUser + Token + Policy intact. Live-token clients keep working +-- untouched; only the stale photocopies are removed. +DELETE FROM SigningCondition; +``` + +Run against each instance's `nsecbunker.db`. If an instance was already +full-wiped, recover by restoring the pre-wipe `nsecbunker.db` backup, then run +the targeted delete. + +> Manual-override grants (`add_signing_condition`, web-approval) also live in +> `SigningCondition`. On an LNbits-only bunker there typically are none, so a +> blanket `DELETE FROM SigningCondition` is safe. If an instance uses manual +> overrides, delete only the policy-derived rows you intend to strip. + +## Keys are never in the DB + +Key material lives in `nsecbunker.json` (`keys`), never in `nsecbunker.db`. A DB +wipe loses ACL/pairing state, never keys. LNbits holds the bunker **admin nsec** +(`LNBITS_NSEC_BUNKER_ADMIN_NSEC`) and is the sole admin client. + +## Schema migrations + +Migrations are applied by the deploy's `prisma migrate deploy`, **not** by the +daemon on boot — the in-`start.js` `npm run prisma:migrate` step is a no-op +(tracked in #31). After adding a migration, make sure the deploy applies it. + +Prisma on NixOS needs the engine env pinned to `prisma-engines_6` (the bare +`prisma-engines` attr is now 7.x with no `libquery_engine.node`; devShell fix +tracked in #30). The deploy's `package.nix` already pins `_6`. From 87e99e487eb4ba62f4c7ba32abd4b406cdc3f741 Mon Sep 17 00:00:00 2001 From: Padreug Date: Sat, 20 Jun 2026 20:50:21 +0200 Subject: [PATCH 36/36] docs: correct prisma-engines + migrate-on-boot accuracy in runbook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - nix devShell uses nixos-25.05's prisma-engines 6.7.0 (has libquery_engine.node) — the 7.x problem is the system/unstable channel only, not the flake's devShell (corrects an earlier overstatement; #30 closed as invalid). - start.js migrate-on-boot is a no-op on nix but IS the migration path on docker (image ENTRYPOINT) — don't assume it's dead everywhere (#31). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/runbook-migrations.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/runbook-migrations.md b/docs/runbook-migrations.md index 9c1dcac..0eee37e 100644 --- a/docs/runbook-migrations.md +++ b/docs/runbook-migrations.md @@ -56,10 +56,16 @@ wipe loses ACL/pairing state, never keys. LNbits holds the bunker **admin nsec** ## Schema migrations -Migrations are applied by the deploy's `prisma migrate deploy`, **not** by the -daemon on boot — the in-`start.js` `npm run prisma:migrate` step is a no-op -(tracked in #31). After adding a migration, make sure the deploy applies it. +On the **nix deploy**, migrations are applied by the deploy's `prisma migrate +deploy`, not by the daemon — `start.js`'s `npm run prisma:migrate` step fails in +the read-only nix store (no `npm` on PATH) and is a redundant no-op there (#31). +On **docker**, by contrast, `start.js` IS the migration path (it's the image +`ENTRYPOINT`), so the step is not dead everywhere. After adding a migration, make +sure the path that applies for your target actually runs it. -Prisma on NixOS needs the engine env pinned to `prisma-engines_6` (the bare -`prisma-engines` attr is now 7.x with no `libquery_engine.node`; devShell fix -tracked in #30). The deploy's `package.nix` already pins `_6`. +Prisma on NixOS: the flake pins **nixos-25.05**, whose `prisma-engines` is +**6.7.0** (ships `libquery_engine.node`) — both the devShell and the deploy's +`package.nix` use it, so `prisma` (and the `npm run test:integration` suite) work +in `nix develop` out of the box. Heads-up: on **nixos-unstable / a system +`` channel**, the bare `prisma-engines` attr is 7.x with no +`libquery_engine.node`; don't run the repo's prisma against an unstable channel.