From 2e663e15130f087b744ad662268104a78db56c17 Mon Sep 17 00:00:00 2001 From: Julien Gautier Date: Sat, 9 May 2026 22:05:54 +0200 Subject: [PATCH] feat(portal-bff): observability foundations (Pino + CLS + OTel) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements ADR-0012 phase 1, BFF side. The SPA wiring is a separate phase-2 PR. Runtime libraries added (production deps): - nestjs-pino, pino, pino-http structured JSON logging - nestjs-cls request-scoped context - @opentelemetry/api / sdk-node / resources / semantic-conventions - @opentelemetry/exporter-trace-otlp-proto OTLP HTTP/Protobuf - @opentelemetry/instrumentation-{http,express,nestjs-core,pg, ioredis,pino} curated, no `auto-instrumentations- node` mass-import (anti-bricolage) Dev dep: pino-pretty (gated by NODE_ENV). Code: - apps/portal-bff/src/observability/tracing.ts — OTel `NodeSDK` bootstrap. Documents the load-order constraint inline (must be the very first import of `main.ts`). Exports nothing — pure side-effect file. - apps/portal-bff/src/observability/observability.module.ts — composes ClsModule (UUID per request stored as `request_id`) and LoggerModule (pino-pretty in dev / raw JSON in prod, LOG_LEVEL env-driven, `/health` excluded from auto-logging). - apps/portal-bff/src/health/{health.controller,health.module}.ts — `GET /api/health` returning `{status, uptimeSeconds, service, version}`. Cheap liveness only — no DB / Redis check; that belongs to a future `/readiness` once dependencies have a readiness story. - apps/portal-bff/src/config/check-database-url.ts — fail-fast validator called from main.ts before NestFactory boots. Catches the same family of bug that bit pgweb in #63: a literal special char in POSTGRES_PASSWORD that needs URL-encoding in DATABASE_URL. Prisma requires a URL string, so we cannot use discrete CLI flags here — early validation + clear error message is the v1 mitigation. Six unit tests cover happy path, missing URL, wrong scheme, encoded special chars, literal `@` in password, malformed URL. Wiring: - main.ts now `import`s `./observability/tracing` as its first line, calls `assertDatabaseUrl()`, then bootstraps Nest with `app.useLogger(app.get(Logger))` from nestjs-pino with `bufferLogs: true` so early-bootstrap lines are not lost. - app.module.ts imports ObservabilityModule first, then the PrismaModule, then HealthModule. - .env.example (BFF and infra/local) document the URL-encoding constraint on POSTGRES_PASSWORD with the exact char-by-char encoding table. Trace ↔ log correlation is automatic via `@opentelemetry/instrumentation-pino`: every Pino record gets `trace_id` / `span_id` injected from the active OTel context. No CLS gymnastics needed for that specific concern. ADR-0012 §Confirmation rewritten to clearly distinguish what landed in this PR (phase 1) from what is wired as the corresponding feature ADRs ship (CLS keys for session/user/ audience, LOG_USER_ID_SALT, redact list, custom spans, SPA-side SDK, full integration tests, prod Collector config). Verified locally: - pnpm exec nx run-many -t lint test build → 8 projects green, 4 test suites for portal-bff, 9 unit tests pass. - `pnpm nx serve portal-bff` boots, `curl /api/health` returns the expected JSON; logs are pretty-printed JSON one-liners on stdout in dev. - `pnpm audit --audit-level=moderate` reports 0 vulnerabilities. --- apps/portal-bff/.env.example | 42 +- apps/portal-bff/src/app/app.module.ts | 4 +- .../src/config/check-database-url.spec.ts | 44 + .../src/config/check-database-url.ts | 54 + .../src/health/health.controller.spec.ts | 26 + .../src/health/health.controller.ts | 26 + apps/portal-bff/src/health/health.module.ts | 7 + apps/portal-bff/src/main.ts | 27 +- .../src/observability/observability.module.ts | 83 ++ apps/portal-bff/src/observability/tracing.ts | 80 ++ .../0012-observability-pino-opentelemetry.md | 31 +- infra/local/.env.example | 9 +- package.json | 16 + pnpm-lock.yaml | 1008 ++++++++++++++++- 14 files changed, 1419 insertions(+), 38 deletions(-) create mode 100644 apps/portal-bff/src/config/check-database-url.spec.ts create mode 100644 apps/portal-bff/src/config/check-database-url.ts create mode 100644 apps/portal-bff/src/health/health.controller.spec.ts create mode 100644 apps/portal-bff/src/health/health.controller.ts create mode 100644 apps/portal-bff/src/health/health.module.ts create mode 100644 apps/portal-bff/src/observability/observability.module.ts create mode 100644 apps/portal-bff/src/observability/tracing.ts diff --git a/apps/portal-bff/.env.example b/apps/portal-bff/.env.example index 185109e..956377b 100644 --- a/apps/portal-bff/.env.example +++ b/apps/portal-bff/.env.example @@ -4,7 +4,35 @@ # Postgres connection (per ADR-0006) # Local dev default: dockerised Postgres on port 5432, schema 'public'. -DATABASE_URL="postgresql://portal:portal@localhost:5432/portal_dev?schema=public" +# Username / password / db must match infra/local/.env (POSTGRES_USER / +# POSTGRES_PASSWORD / POSTGRES_DB) — those are the source of truth, +# this is the BFF view of the same connection. +# +# IMPORTANT — URL encoding. The password is part of the URL userinfo +# segment, so any of these characters must be URL-encoded: +# @ → %40 # → %23 : → %3A / → %2F ? → %3F +# % → %25 & → %26 = → %3D + → %2B ; → %3B +# i.e. if your POSTGRES_PASSWORD is "p@ss#1", DATABASE_URL must read +# "postgresql://portal:p%40ss%231@localhost:5432/portal_dev?schema=public" +# The BFF aborts at boot with a clear error if it detects an unencoded +# special character (see apps/portal-bff/src/config/check-database-url.ts). +DATABASE_URL="postgresql://portal:portal_dev_change_me@localhost:5432/portal_dev?schema=public" + +# Observability (per ADR-0012) +# All OTEL_* keys are honoured by the OpenTelemetry SDK directly — see +# apps/portal-bff/src/observability/tracing.ts for the bootstrap. +# Pino log level: 'info' in prod, 'debug' in dev (default if unset). +LOG_LEVEL=debug +OTEL_SERVICE_NAME=portal-bff +OTEL_SERVICE_VERSION=dev +# Default endpoint targets the Collector provisioned in +# infra/local/dev.compose.yml. The /v1/traces suffix is required by +# the HTTP/Protobuf transport. +OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318/v1/traces +OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf +# v1 samples 100 % at the app; tail sampling is delegated to the +# Collector (per ADR-0012). Override only for spike investigations. +OTEL_TRACES_SAMPLER=always_on # Future env vars introduced by upcoming phases / ADRs: # @@ -28,15 +56,9 @@ DATABASE_URL="postgresql://portal:portal@localhost:5432/portal_dev?schema=public # MFA (ADR-0011): # MFA_FRESHNESS_SECONDS (default 600) # -# Observability (ADR-0012): -# LOG_LEVEL ('info' in prod, 'debug' in dev) -# LOG_USER_ID_SALT (per-environment salt) -# OTEL_SERVICE_NAME ('portal-bff') -# OTEL_SERVICE_VERSION -# OTEL_RESOURCE_ATTRIBUTES -# OTEL_EXPORTER_OTLP_ENDPOINT -# OTEL_EXPORTER_OTLP_PROTOCOL ('http/protobuf') -# OTEL_TRACES_SAMPLER ('always_on' in v1) +# Observability — additional keys to be wired as features land: +# LOG_USER_ID_SALT (per-environment salt for hashing user_id +# in CLS context — needed once auth lands) # # Audit trail (ADR-0013): # AUDIT_DATABASE_URL (separate creds, role 'audit_writer') diff --git a/apps/portal-bff/src/app/app.module.ts b/apps/portal-bff/src/app/app.module.ts index 137b986..917bbba 100644 --- a/apps/portal-bff/src/app/app.module.ts +++ b/apps/portal-bff/src/app/app.module.ts @@ -2,9 +2,11 @@ import { Module } from '@nestjs/common'; import { PrismaModule } from 'nestjs-prisma'; import { AppController } from './app.controller'; import { AppService } from './app.service'; +import { ObservabilityModule } from '../observability/observability.module'; +import { HealthModule } from '../health/health.module'; @Module({ - imports: [PrismaModule.forRoot({ isGlobal: true })], + imports: [ObservabilityModule, PrismaModule.forRoot({ isGlobal: true }), HealthModule], controllers: [AppController], providers: [AppService], }) diff --git a/apps/portal-bff/src/config/check-database-url.spec.ts b/apps/portal-bff/src/config/check-database-url.spec.ts new file mode 100644 index 0000000..69a68b9 --- /dev/null +++ b/apps/portal-bff/src/config/check-database-url.spec.ts @@ -0,0 +1,44 @@ +import { assertDatabaseUrl } from './check-database-url'; + +describe('assertDatabaseUrl', () => { + const original = process.env['DATABASE_URL']; + + afterEach(() => { + if (original === undefined) { + delete process.env['DATABASE_URL']; + } else { + process.env['DATABASE_URL'] = original; + } + }); + + it('passes for a well-formed URL with a URL-safe password', () => { + process.env['DATABASE_URL'] = 'postgresql://user:safePass123@localhost:5432/db?schema=public'; + expect(() => assertDatabaseUrl()).not.toThrow(); + }); + + it('passes for a password whose special chars are URL-encoded', () => { + // Original password contained `@` and `#` — encoded as %40 and %23. + process.env['DATABASE_URL'] = 'postgresql://user:p%40ss%23word@localhost:5432/db'; + expect(() => assertDatabaseUrl()).not.toThrow(); + }); + + it('throws when DATABASE_URL is unset', () => { + delete process.env['DATABASE_URL']; + expect(() => assertDatabaseUrl()).toThrow(/not set/); + }); + + it('throws when DATABASE_URL has the wrong scheme', () => { + process.env['DATABASE_URL'] = 'mysql://user:pass@localhost/db'; + expect(() => assertDatabaseUrl()).toThrow(/postgresql:/); + }); + + it('throws when the password contains a literal @ (multiple @ in URL)', () => { + process.env['DATABASE_URL'] = 'postgresql://user:p@ss@localhost:5432/db'; + expect(() => assertDatabaseUrl()).toThrow(/URL-encoding/); + }); + + it('throws on a fundamentally malformed URL', () => { + process.env['DATABASE_URL'] = 'not a url at all'; + expect(() => assertDatabaseUrl()).toThrow(/not a valid URL/); + }); +}); diff --git a/apps/portal-bff/src/config/check-database-url.ts b/apps/portal-bff/src/config/check-database-url.ts new file mode 100644 index 0000000..65a48f9 --- /dev/null +++ b/apps/portal-bff/src/config/check-database-url.ts @@ -0,0 +1,54 @@ +/** + * Sanity-check `DATABASE_URL` early in bootstrap so a malformed value + * fails fast with a clear, actionable message instead of an opaque + * Prisma error deep into the request lifecycle. + * + * The most common malformation is a literal special character in + * POSTGRES_PASSWORD that the contributor forgot to URL-encode (`@`, + * `#`, `:`, `/`, `?`, `%`, `&`, `=`, `+`, `;` all require it). This + * is the same family of bug that bit pgweb in #63 — pgweb's compose + * was switched to discrete CLI flags to bypass URL parsing entirely, + * but Prisma requires a URL string, so we have no equivalent escape + * hatch here. Documentation + early validation are the v1 fix. + */ + +const URL_ENCODE_HINT = + 'If POSTGRES_PASSWORD contains special characters (@ # : / ? % & = + ;), ' + + 'they must be URL-encoded in DATABASE_URL — e.g., "@" → "%40", "#" → "%23". ' + + 'See apps/portal-bff/.env.example for the canonical form.'; + +export function assertDatabaseUrl(): void { + const raw = process.env['DATABASE_URL']; + if (!raw) { + throw new Error( + 'DATABASE_URL is not set. Copy apps/portal-bff/.env.example to ' + + 'apps/portal-bff/.env and adjust.', + ); + } + + let parsed: URL; + try { + parsed = new URL(raw); + } catch { + throw new Error(`DATABASE_URL is not a valid URL. ${URL_ENCODE_HINT}`); + } + + if (parsed.protocol !== 'postgresql:' && parsed.protocol !== 'postgres:') { + throw new Error( + `DATABASE_URL must use the "postgresql://" scheme; got "${parsed.protocol}".`, + ); + } + + // Heuristic — multiple "@" before the path almost always means the + // password contains a literal "@" that should have been encoded. + // Splitting on the parsed pathname isolates the userinfo+host + // segment without depending on scheme-specific quirks. + const beforePath = raw.split(parsed.pathname || '/')[0] ?? raw; + const atCount = (beforePath.match(/@/g) ?? []).length; + if (atCount > 1) { + throw new Error( + `DATABASE_URL has ${atCount} "@" before the database path — your password almost ` + + `certainly needs URL-encoding. ${URL_ENCODE_HINT}`, + ); + } +} diff --git a/apps/portal-bff/src/health/health.controller.spec.ts b/apps/portal-bff/src/health/health.controller.spec.ts new file mode 100644 index 0000000..3c4553d --- /dev/null +++ b/apps/portal-bff/src/health/health.controller.spec.ts @@ -0,0 +1,26 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { HealthController } from './health.controller'; + +describe('HealthController', () => { + let app: TestingModule; + + beforeAll(async () => { + app = await Test.createTestingModule({ + controllers: [HealthController], + }).compile(); + }); + + describe('liveness', () => { + it('returns status ok with process metadata', () => { + const controller = app.get(HealthController); + const result = controller.liveness(); + + expect(result).toMatchObject({ + status: 'ok', + service: expect.any(String), + version: expect.any(String), + }); + expect(result.uptimeSeconds).toBeGreaterThanOrEqual(0); + }); + }); +}); diff --git a/apps/portal-bff/src/health/health.controller.ts b/apps/portal-bff/src/health/health.controller.ts new file mode 100644 index 0000000..7882ce2 --- /dev/null +++ b/apps/portal-bff/src/health/health.controller.ts @@ -0,0 +1,26 @@ +import { Controller, Get } from '@nestjs/common'; + +/** + * Liveness endpoint. Returns 200 OK with minimal process metadata. + * Intentionally cheap (no DB / Redis / downstream check) so it can + * be hit by container orchestrators (Kubernetes, Compose healthcheck) + * without amplifying load on backing services. + * + * A separate `/readiness` endpoint will land alongside the first + * dependency that has a readiness story to tell (Postgres pool warm, + * Redis connection established, etc.). + */ +@Controller('health') +export class HealthController { + private readonly startedAt = Date.now(); + + @Get() + liveness(): { status: 'ok'; uptimeSeconds: number; service: string; version: string } { + return { + status: 'ok', + uptimeSeconds: Math.floor((Date.now() - this.startedAt) / 1000), + service: process.env['OTEL_SERVICE_NAME'] ?? 'portal-bff', + version: process.env['OTEL_SERVICE_VERSION'] ?? 'dev', + }; + } +} diff --git a/apps/portal-bff/src/health/health.module.ts b/apps/portal-bff/src/health/health.module.ts new file mode 100644 index 0000000..7476abe --- /dev/null +++ b/apps/portal-bff/src/health/health.module.ts @@ -0,0 +1,7 @@ +import { Module } from '@nestjs/common'; +import { HealthController } from './health.controller'; + +@Module({ + controllers: [HealthController], +}) +export class HealthModule {} diff --git a/apps/portal-bff/src/main.ts b/apps/portal-bff/src/main.ts index 63006ce..765f69a 100644 --- a/apps/portal-bff/src/main.ts +++ b/apps/portal-bff/src/main.ts @@ -1,9 +1,25 @@ -import { Logger, ValidationPipe } from '@nestjs/common'; +// MUST be the very first import — see apps/portal-bff/src/observability/tracing.ts +// for the reasoning. Anything `import`ed above this line bypasses the +// OpenTelemetry auto-instrumentations and is silently un-traced. +import './observability/tracing'; + +import { ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; +import { Logger } from 'nestjs-pino'; import { AppModule } from './app/app.module'; +import { assertDatabaseUrl } from './config/check-database-url'; + +// Fail fast on a malformed DATABASE_URL (most often a special char in +// the password that needs URL-encoding) rather than letting Prisma +// surface a cryptic "invalid connection string" error mid-request. +assertDatabaseUrl(); async function bootstrap() { - const app = await NestFactory.create(AppModule); + // `bufferLogs: true` holds early-bootstrap log lines until the + // Pino-based Logger is wired in below, so we don't lose anything + // emitted before `app.useLogger()`. + const app = await NestFactory.create(AppModule, { bufferLogs: true }); + app.useLogger(app.get(Logger)); app.useGlobalPipes( new ValidationPipe({ @@ -18,9 +34,12 @@ async function bootstrap() { const globalPrefix = 'api'; app.setGlobalPrefix(globalPrefix); - const port = process.env['PORT'] || 3000; + const port = process.env['PORT'] ?? 3000; await app.listen(port); - Logger.log(`Application is running on: http://localhost:${port}/${globalPrefix}`); + + app + .get(Logger) + .log(`Application is running on: http://localhost:${port}/${globalPrefix}`, 'Bootstrap'); } bootstrap(); diff --git a/apps/portal-bff/src/observability/observability.module.ts b/apps/portal-bff/src/observability/observability.module.ts new file mode 100644 index 0000000..67cc189 --- /dev/null +++ b/apps/portal-bff/src/observability/observability.module.ts @@ -0,0 +1,83 @@ +/** + * Observability wiring for the BFF (per ADR-0012). + * + * Composes: + * - `nestjs-cls` for request-scoped context. v1 stores `request_id` + * (UUID per inbound request); `session_id`, `user_id_hash`, and + * `audience` keys are reserved for future ADR-0009 / ADR-0010 + * work and are populated by guards/interceptors as those modules + * land. + * - `nestjs-pino` for structured JSON logs. In dev (`NODE_ENV !== + * 'production'`) we pipe through `pino-pretty` so the developer + * sees colourised, human-readable lines on stdout. In prod the + * raw JSON output is shipped via the container runtime's stdout + * pipeline (per ADR-0012 §"stdout + OTLP shipping"). + * + * Trace ↔ log correlation: handled outside this module by + * `@opentelemetry/instrumentation-pino` (loaded in `tracing.ts`), + * which auto-injects `trace_id` / `span_id` into every Pino log + * record from the active OTel context. + */ + +import { Module } from '@nestjs/common'; +import { ClsModule } from 'nestjs-cls'; +import { LoggerModule } from 'nestjs-pino'; +import { randomUUID } from 'node:crypto'; + +const isProduction = process.env['NODE_ENV'] === 'production'; +const logLevel = process.env['LOG_LEVEL'] ?? (isProduction ? 'info' : 'debug'); + +@Module({ + imports: [ + ClsModule.forRoot({ + global: true, + middleware: { + mount: true, + generateId: true, + // UUID v4 per request — exposed to logs as `request_id` and + // available everywhere via `cls.get('request_id')`. Stored + // under the conventional `id` key by nestjs-cls; we + // surface it through Pino's `customProps` below. + idGenerator: () => randomUUID(), + }, + }), + LoggerModule.forRoot({ + pinoHttp: { + level: logLevel, + // Pretty-print only in dev. In prod the JSON stream is + // consumed by the container runtime / Collector. + ...(isProduction + ? {} + : { + transport: { + target: 'pino-pretty', + options: { + singleLine: true, + translateTime: 'SYS:HH:MM:ss.l', + }, + }, + }), + // Hide some noise that has nothing to do with the work being + // done. Health-check pings would drown out everything else. + autoLogging: { + ignore: (req) => req.url === '/api/health' || req.url === '/health', + }, + // Re-key the request id so it surfaces under `request_id` + // (snake_case, ADR-0012 convention) instead of pino's + // default `req.id` / `reqId`. + customProps: () => ({}), + genReqId: (req) => { + // Honour an inbound `X-Request-Id` header when present — + // useful for end-to-end tracing across systems that propagate + // it. Otherwise generate a fresh UUID v4. The same id is + // used by the CLS middleware above (Nest-Pino integrates + // with nestjs-cls automatically when both modules are + // imported). + const incoming = req.headers['x-request-id']; + return typeof incoming === 'string' && incoming.length > 0 ? incoming : randomUUID(); + }, + }, + }), + ], +}) +export class ObservabilityModule {} diff --git a/apps/portal-bff/src/observability/tracing.ts b/apps/portal-bff/src/observability/tracing.ts new file mode 100644 index 0000000..6f46bfb --- /dev/null +++ b/apps/portal-bff/src/observability/tracing.ts @@ -0,0 +1,80 @@ +/** + * OpenTelemetry SDK bootstrap for the BFF (per ADR-0012). + * + * IMPORTANT — module load order + * ───────────────────────────── + * This file must be `import`ed (or `require`d) BEFORE any other module + * that creates HTTP clients, DB clients, web frameworks, etc. The + * auto-instrumentations work by patching modules at require time; they + * miss anything already loaded into Node's module cache. In `main.ts` + * we therefore have: + * + * import './observability/tracing'; // first line, no other imports above it + * // ... rest of the bootstrap ... + * + * Anything else above that line will be silently un-instrumented. + * + * What this enables, out of the box + * ───────────────────────────────── + * - HTTP, Express, NestJS request spans (incoming and outgoing) + * - PostgreSQL spans via Prisma (the underlying `pg` driver) + * - Redis (`ioredis`) spans — wired in advance for ADR-0010 / ADR-0014 + * - Pino log records auto-decorated with the active `trace_id`/`span_id` + * so log lines correlate with traces in the backend + * + * Sampling is 100% at the app per ADR-0012; tail sampling is delegated + * to the OTel Collector. Transport is OTLP HTTP/Protobuf (`port 4318`) + * to match the .env.example default and avoid the gRPC binary + * dependency (`@grpc/grpc-js`). + */ + +import { NodeSDK } from '@opentelemetry/sdk-node'; +import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'; +import { resourceFromAttributes } from '@opentelemetry/resources'; +import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions'; +import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; +import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'; +import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core'; +import { PgInstrumentation } from '@opentelemetry/instrumentation-pg'; +import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis'; +import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino'; + +const serviceName = process.env['OTEL_SERVICE_NAME'] ?? 'portal-bff'; +const serviceVersion = process.env['OTEL_SERVICE_VERSION'] ?? 'dev'; +const otlpEndpoint = + process.env['OTEL_EXPORTER_OTLP_ENDPOINT'] ?? 'http://localhost:4318/v1/traces'; + +const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + [ATTR_SERVICE_NAME]: serviceName, + [ATTR_SERVICE_VERSION]: serviceVersion, + }), + traceExporter: new OTLPTraceExporter({ url: otlpEndpoint }), + instrumentations: [ + new HttpInstrumentation(), + new ExpressInstrumentation(), + new NestInstrumentation(), + new PgInstrumentation(), + new IORedisInstrumentation(), + new PinoInstrumentation(), + ], +}); + +sdk.start(); + +// Graceful shutdown on container-stop signals so in-flight spans get a +// chance to flush to the collector. The 2s timeout is generous in dev +// and fast enough not to block container teardown in prod. +const shutdown = (signal: string): void => { + sdk + .shutdown() + .catch((err) => { + // Best-effort cleanup — log to stderr because Pino may itself + // be in the middle of shutting down. + process.stderr.write(`OpenTelemetry shutdown error on ${signal}: ${String(err)}\n`); + }) + .finally(() => process.exit(0)); +}; + +process.once('SIGTERM', () => shutdown('SIGTERM')); +process.once('SIGINT', () => shutdown('SIGINT')); diff --git a/docs/decisions/0012-observability-pino-opentelemetry.md b/docs/decisions/0012-observability-pino-opentelemetry.md index ba00829..87d3bb9 100644 --- a/docs/decisions/0012-observability-pino-opentelemetry.md +++ b/docs/decisions/0012-observability-pino-opentelemetry.md @@ -188,18 +188,25 @@ The BFF refuses to start if `LOG_USER_ID_SALT` or `OTEL_SERVICE_NAME` is missing ### Confirmation -- `apps/portal-bff/src/observability/observability.module.ts` registers `nestjs-pino`, `nestjs-cls`, the OTel SDK initialiser, and the redact-list test fixture. -- `apps/portal-bff/src/main.ts` calls `tracingSetup()` _before_ `NestFactory.create(AppModule)` — OTel must be initialised before any auto-instrumented module is loaded. -- The Pino transport in dev uses `pino-pretty` (human-readable); prod emits raw JSON. -- `apps/portal-shell/src/observability/tracing.ts` initialises `@opentelemetry/sdk-trace-web` with the OTLP/HTTP exporter pointing to the BFF's `/v1/traces` ingress (or directly to the collector if exposed). -- Every controller receives `req` and `res` and the http auto-instrumentation produces a span; non-trivial service methods open custom spans via `tracer.startActiveSpan('domain.', ...)` and propagate the CLS context within them. -- Integration tests: - - a single user-action request emits one trace with correct parent-child structure (SPA → BFF → DB); - - every log line for that request carries the same `trace_id`; - - the redact list strips its targets from a captured stream; - - a missing `LOG_USER_ID_SALT` prevents BFF startup. -- The CLS-bound `user_id_hash` is identical for two consecutive requests of the same user, and different across environments (different salt). -- The OTel Collector configuration ships in the deployment manifest (covered by the future infrastructure ADR), not in source — the application remains backend-agnostic. +**Wired in the BFF foundation PR (phase 1):** + +- `apps/portal-bff/src/observability/tracing.ts` initialises the OTel `NodeSDK` with the OTLP HTTP/Protobuf exporter (target: `OTEL_EXPORTER_OTLP_ENDPOINT`, default `http://localhost:4318/v1/traces`). +- `apps/portal-bff/src/main.ts` `import`s `./observability/tracing` as its very first line — anything above it bypasses auto-instrumentation. +- `apps/portal-bff/src/observability/observability.module.ts` registers `nestjs-cls` (mounted as global middleware, populates `request_id` as a per-request UUID) and `nestjs-pino` (`LoggerModule`, `pino-pretty` in dev / raw JSON in prod, `LOG_LEVEL` env-driven, `/health` excluded from auto-logging). +- Auto-instrumentations active in v1: HTTP, Express, NestJS, PostgreSQL (`pg` driver under Prisma), IORedis (pre-wired for ADR-0010 / ADR-0014), and Pino. The Pino instrumentation auto-decorates every log record with `trace_id` and `span_id` from the active OTel context, so log ↔ trace correlation is automatic. +- `apps/portal-bff/src/health/health.controller.ts` exposes `GET /api/health` (cheap liveness — process metadata only, no DB / Redis / downstream check). +- `apps/portal-bff/.env.example` declares `LOG_LEVEL`, `OTEL_SERVICE_NAME`, `OTEL_SERVICE_VERSION`, `OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_PROTOCOL`, `OTEL_TRACES_SAMPLER` with sensible dev defaults. + +**Wired as the corresponding features land:** + +- CLS keys `session_id`, `user_id_hash`, `audience` — populated by guards/interceptors when ADR-0009 / ADR-0010 land. +- `LOG_USER_ID_SALT` enforced (BFF refuses to start without it) — same trigger. +- Pino `redact` list for PII paths — wired alongside the first DTO that carries a redactable field. +- Custom spans `tracer.startActiveSpan('domain.', …)` — added per service method that warrants one (creating a row, calling a downstream, etc.). +- SPA-side `@opentelemetry/sdk-trace-web` initialiser, OTLP/HTTP exporter targeting the Collector, `traceparent` header propagated to the BFF — phase-2 PR. +- Integration tests: full SPA → BFF → DB trace with correct parent-child structure; every log line for one request carries the same `trace_id`; redact list strips its targets — wired with the auth + first real screen. +- A separate `/readiness` endpoint that probes Postgres / Redis / OBO cache — wired with the first dependency that has a readiness story to tell. +- OTel Collector deployment configuration in the runtime manifest — phase 3b on-prem ADR. The application stays backend-agnostic (any OTLP-capable Collector works). ## Pros and Cons of the Options diff --git a/infra/local/.env.example b/infra/local/.env.example index c4a8454..bf7e67f 100644 --- a/infra/local/.env.example +++ b/infra/local/.env.example @@ -5,7 +5,14 @@ # $EDITOR .env # ---------------------------------------------------------------- Postgres -# `POSTGRES_PASSWORD` is mandatory — the compose refuses to boot without it. +# `POSTGRES_PASSWORD` is mandatory — the compose refuses to boot +# without it. +# +# Picking a password — keep it URL-safe in dev. The BFF reads its +# Postgres URL via `DATABASE_URL` and Prisma demands the URL form; +# any `@`, `#`, `:`, `/`, `?`, `%`, `&`, `=`, `+`, `;` in the +# password must be URL-encoded in `apps/portal-bff/.env`. Easiest +# avoided by sticking to alphanumerics + `-_.~` in dev. POSTGRES_USER=portal POSTGRES_PASSWORD=portal_dev_change_me POSTGRES_DB=portal_dev diff --git a/package.json b/package.json index b3925e1..680896d 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "jsonc-eslint-parser": "^2.1.0", "lint-staged": "^17.0.0", "nx": "22.7.1", + "pino-pretty": "^13.1.3", "postcss": "^8.5.12", "prettier": "^3.8.1", "prisma": "^6.19.3", @@ -119,11 +120,26 @@ "@nestjs/common": "^11.0.0", "@nestjs/core": "^11.0.0", "@nestjs/platform-express": "^11.0.0", + "@opentelemetry/api": "^1.9.1", + "@opentelemetry/exporter-trace-otlp-proto": "^0.217.0", + "@opentelemetry/instrumentation-express": "^0.65.0", + "@opentelemetry/instrumentation-http": "^0.217.0", + "@opentelemetry/instrumentation-ioredis": "^0.65.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.63.0", + "@opentelemetry/instrumentation-pg": "^0.69.0", + "@opentelemetry/instrumentation-pino": "^0.63.0", + "@opentelemetry/resources": "^2.7.1", + "@opentelemetry/sdk-node": "^0.217.0", + "@opentelemetry/semantic-conventions": "^1.40.0", "@prisma/client": "^6.19.3", "axios": "^1.6.0", "class-transformer": "^0.5.1", "class-validator": "^0.15.1", + "nestjs-cls": "^6.2.0", + "nestjs-pino": "^4.6.1", "nestjs-prisma": "^0.27.0", + "pino": "^10.3.1", + "pino-http": "^11.0.0", "reflect-metadata": "^0.2.0", "rxjs": "~7.8.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2952d90..698b730 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,39 @@ importers: '@nestjs/platform-express': specifier: ^11.0.0 version: 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19) + '@opentelemetry/api': + specifier: ^1.9.1 + version: 1.9.1 + '@opentelemetry/exporter-trace-otlp-proto': + specifier: ^0.217.0 + version: 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-express': + specifier: ^0.65.0 + version: 0.65.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-http': + specifier: ^0.217.0 + version: 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-ioredis': + specifier: ^0.65.0 + version: 0.65.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-nestjs-core': + specifier: ^0.63.0 + version: 0.63.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-pg': + specifier: ^0.69.0 + version: 0.69.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-pino': + specifier: ^0.63.0 + version: 0.63.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': + specifier: ^2.7.1 + version: 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-node': + specifier: ^0.217.0 + version: 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': + specifier: ^1.40.0 + version: 1.40.0 '@prisma/client': specifier: ^6.19.3 version: 6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3) @@ -56,9 +89,21 @@ importers: class-validator: specifier: ^0.15.1 version: 0.15.1 + nestjs-cls: + specifier: ^6.2.0 + version: 6.2.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) + nestjs-pino: + specifier: ^4.6.1 + version: 4.6.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.3.1)(rxjs@7.8.2) nestjs-prisma: specifier: ^0.27.0 version: 0.27.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@prisma/client@6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3))(chokidar@5.0.0)(prisma@6.19.3(typescript@5.9.3)) + pino: + specifier: ^10.3.1 + version: 10.3.1 + pino-http: + specifier: ^11.0.0 + version: 11.0.0 reflect-metadata: specifier: ^0.2.0 version: 0.2.2 @@ -219,6 +264,9 @@ importers: nx: specifier: 22.7.1 version: 22.7.1(@swc-node/register@1.11.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@swc/core@1.15.33(@swc/helpers@0.5.21))(@swc/types@0.1.26)(typescript@5.9.3))(@swc/core@1.15.33(@swc/helpers@0.5.21)) + pino-pretty: + specifier: ^13.1.3 + version: 13.1.3 postcss: specifier: ^8.5.12 version: 8.5.14 @@ -251,7 +299,7 @@ importers: version: 8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4) vitest: specifier: ^4.0.8 - version: 4.1.5(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) + version: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) webpack-cli: specifier: ^5.1.4 version: 5.1.4(webpack@5.106.2) @@ -266,7 +314,7 @@ importers: version: 2.8.1 vitest: specifier: ^4.0.8 - version: 4.1.5(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) + version: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) libs/shared/util: dependencies: @@ -278,7 +326,7 @@ importers: version: 2.8.1 vitest: specifier: ^4.0.8 - version: 4.1.5(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) + version: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) packages: @@ -1599,6 +1647,15 @@ packages: resolution: {integrity: sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==} engines: {node: ^20.17.0 || >=22.9.0} + '@grpc/grpc-js@1.14.3': + resolution: {integrity: sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==} + engines: {node: '>=12.10.0'} + + '@grpc/proto-loader@0.8.1': + resolution: {integrity: sha512-wtF6h+DY6M3YaDBPAmvuuA6jV8Sif9MjtOI5euKFWRgCDl5PeDpPsHR9u2l6St5ceY8AZgoNDww5+HvEsXFsGg==} + engines: {node: '>=6'} + hasBin: true + '@harperfast/extended-iterable@1.0.3': resolution: {integrity: sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==} @@ -1951,6 +2008,9 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@js-sdsl/ordered-map@4.4.2': + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + '@jsonjoy.com/base64@1.1.2': resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} engines: {node: '>=10.0'} @@ -2703,6 +2763,220 @@ packages: '@nx/workspace@22.7.1': resolution: {integrity: sha512-wnBMgeogdGaRdxDDzZspSt1U87PMeYJhz1ygr42L9Lot9E5nCf17E85iyHl3YxcMSNslHxnHyTkq7MyQ8hHjdQ==} + '@opentelemetry/api-logs@0.217.0': + resolution: {integrity: sha512-Cdq0jW2lknrNfrAm92MyEAvpe2cRsKjdnQLHUL6xRA4IVUnsWx6P65E7NcUO0Y+L4w1Aee5iV8FvjSwd+lrs9A==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/api@1.9.1': + resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/configuration@0.217.0': + resolution: {integrity: sha512-xCtrYOhBqdy6ZOMfe0Oa73ZKF+2LMhoOv4L5vmwAHVvOXUg+V3fvKuEIr9ZyD0Ow+vxllEjWO6PV1wd0DOtyvw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.9.0 + + '@opentelemetry/context-async-hooks@2.7.1': + resolution: {integrity: sha512-OPFBYuXEn1E4ja3Y6eeA7O+ZnLBNcXTV5Cgsn1VaqBZ6hC5FnpZPLBNme1LJY8ZtF4aOujPKFoeWN4ik487KuQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@2.7.1': + resolution: {integrity: sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/exporter-logs-otlp-grpc@0.217.0': + resolution: {integrity: sha512-vC5S0Dc+noxD86CVtNu1+awCHPA5Kewi1Sg23ps+9lh4YifwsKXh3pe4XTNEKtUJiAcjpJ5dqStGakLbrSE+YQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-logs-otlp-http@0.217.0': + resolution: {integrity: sha512-KfLAdt1uilVE+3FxbgVnp2ZrzqbIawzcesnRoi+Kh9ckB5Ld5D8btUgoBvwTbdmuNx1j6b132Wsh72azq+pPNQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-logs-otlp-proto@0.217.0': + resolution: {integrity: sha512-Se0GG/ZO24mQTlQj7zprR4pNI0nKe4lPDPBsuJmi6508b9TlZEuUd3EfyuHk6oJxzL7fGyDFYAbxNigQvRP2ZQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-metrics-otlp-grpc@0.217.0': + resolution: {integrity: sha512-0GpJKnCoVaVA1rKBMVPHziznfOQlXgH72S9ktjBAF1AnAVPzX7vVEBGrhwiSxxHDAiefXk+J8znApsMb/K6Z3w==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-metrics-otlp-http@0.217.0': + resolution: {integrity: sha512-1zkMzzhiNJdVmLxuwkltqWGw4fOOam47bqRxmuQNjyKJe/9NmY5cIrZ4kiQV7sVGxoOgT0ZvGUfLcjvtpC/b9Q==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-metrics-otlp-proto@0.217.0': + resolution: {integrity: sha512-nfxt/KxVGFkjkO/M+58y1ugHu/dwPtxG4eYq0KApcQ7xk5CHzhdn+IuLZfDSvNDrJ3Uy5q++Fj/wbK7i8yryfQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-prometheus@0.217.0': + resolution: {integrity: sha512-U9MCXxJu0sBCh5aEkylYRR4xVIL8D1CW6dGwvYXbfFr0qveSorfD0XJchCAWoW6QfAAIcY/yxjf4Dj8OgkHBPw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-trace-otlp-grpc@0.217.0': + resolution: {integrity: sha512-fPZs2fw7veLH3pEKu8vSepUa2fQpAE2P7al6qU10aH9GrEJJ8YaPgsd5xON7by5rbcEVS71FOU2aWyK6nzB7VQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-trace-otlp-http@0.217.0': + resolution: {integrity: sha512-38YQoqtYjglz2GV94LGUN/djLvxtvGIQO68o6qAFPVshjmwSdX1F2i0c7vn3lEl1L5B/YqjB/bgKXaVx7KO+RQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-trace-otlp-proto@0.217.0': + resolution: {integrity: sha512-nPV8gKHUiSuTZpQcnZU3/pBlK7crSyEGpZuh5MtWySB0vv6NNG0QvvfKitQt+Fc2Mc6qfyU54KlZcurwoTbrVg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-zipkin@2.7.1': + resolution: {integrity: sha512-mfsD9bKAxcKrh5+y08TPodvClBO0CznBE3p79YAGnO81WI4LrdsGA65T53e4iTSbCalW4WaUpkbeJcbpyIUHfg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/instrumentation-express@0.65.0': + resolution: {integrity: sha512-Z22sVuMYUKGnEFO1ovlC4iKQubSKv8AlP8NxvYHM3hlD023GaC6YV5WW4fapGyvIDUnN++Cll3ZjGT689T3YZQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-http@0.217.0': + resolution: {integrity: sha512-B88Y7k5A9a60pHUboFoeJlgVwXq2T0rsZKj6dTwzSMKSOsNXR4Jz5ovwprVn3kHLAZrkyLEjQtBJ34DYHs1U4Q==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-ioredis@0.65.0': + resolution: {integrity: sha512-ZOy2m2JRTAsxA3Y02j0QsDm976PF8wA5LdjfbIrSWgACekJEt28uKFXoAc/ufqyVGvgsGACN/A8V92usset2qA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-nestjs-core@0.63.0': + resolution: {integrity: sha512-uw27m1wSx4AjC+9qfKHlY4IZDQxB9+YR42jJoS5wZcAzhTD95vW8JKIt8oqfcCMBlzTk7LBlaO0J7PTdAVTWkA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-pg@0.69.0': + resolution: {integrity: sha512-5tHz2AOyuYaWJePxybooIHPlV8v1EPBwrgFlfuuGXBV/EFnnQME+KEPJ9u9e3oe2aKd0gi8CEkTzZ61VwuWo5g==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-pino@0.63.0': + resolution: {integrity: sha512-3OIHBN/bGKXgqeqNYnXb+eXJJx+MhXLzolNiFZR0eR7HUXv+rqj6P3J5LFFhrQzrTTD/huePTYidhJl87vLdow==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation@0.217.0': + resolution: {integrity: sha512-24ucQMjz7Y34Kw3trbxL2ZrssbtgWnR+Clpaa+YdeWuuyH3Cvk23Q03PcQvqiZrDvt8AmQmjgg9v6Y9PHoxG7w==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-exporter-base@0.217.0': + resolution: {integrity: sha512-eYfqnB3UhKu/5frhd1R6+FprKygbhkomuaceMXDyzxbfXB9tKgZOVmjaJ02CkLA6Tdzumxl+e2H+vo2a8jiMPQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-grpc-exporter-base@0.217.0': + resolution: {integrity: sha512-7RTAdZuOsCDnsyqTCG4+bDzrfnsWdzkRs7z0AVi/V3tEQx0oKeyc+OuRWYxnRsmaJXgxcmB8vb/lfxn58Dj6Ag==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-transformer@0.217.0': + resolution: {integrity: sha512-MKK8UHKFUOGAvbZRWh90MhwHG+Fxm6OROBdjKPCF+HQobjuJ/Kuf8Chs8CR45X1aqotxrMj7OxTdsXe8sXuGVA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/propagator-b3@2.7.1': + resolution: {integrity: sha512-RJid6E2CKyeGfKBzXKF21ejabGMHypFkPAh3qZ+NvI+SGjuIye79t3PmiqcDgtRzdKH6ynXzbfslQ8DfpRUg2A==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/propagator-jaeger@2.7.1': + resolution: {integrity: sha512-KMjVBHzP4N60bOzxja76M1F1hZZ43lGPga5ix+mkv9+kk1nx9SbkxSvJsMbuVUxdPQmsPTqGShmhN8ulrMOg6Q==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/redis-common@0.38.3': + resolution: {integrity: sha512-VCghU1JYs/4gP6Gqf/xro9MEsZ7LrMv2uONVsaESKL38ZOB9BqnI98FfS23wjMnHlpuE+TTaWSoAVNpTwYXzjw==} + engines: {node: ^18.19.0 || >=20.6.0} + + '@opentelemetry/resources@2.7.1': + resolution: {integrity: sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-logs@0.217.0': + resolution: {integrity: sha512-BB+PcHItcZDL63dPMW+mJvwN9rk37wuIDjRxbVlg6pPDvDR/7GL7UJHbGsllgoggOoTimsKgENaWPoGch/oE1A==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.10.0' + + '@opentelemetry/sdk-metrics@2.7.1': + resolution: {integrity: sha512-MpDJdkiFDs3Pm1RHO3KByuZbuBdJEXEAkiC0+yJdsZGVCdf1RpHR6n+LHDcS7ffmfrt5kVCzJSCfm4z2C7v0uQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.9.0 <1.10.0' + + '@opentelemetry/sdk-node@0.217.0': + resolution: {integrity: sha512-K/60pSv42+NQiZKy1pAH18nYDkxltsDV4O3SJ233J0E9raU1ksyL9gsKuS8p30bYBb4AMPCfDuutHQaHYpcv0Q==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-trace-base@2.7.1': + resolution: {integrity: sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-trace-node@2.7.1': + resolution: {integrity: sha512-pCpQxU68lV+I9s9svqMyVu5iHdDDUnqUpSxqwyCU8A9ejEsSnMPCbearwsUO4yk08ZJzAIUCFuReMdVQvHrdvg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/semantic-conventions@1.40.0': + resolution: {integrity: sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==} + engines: {node: '>=14'} + + '@opentelemetry/sql-common@0.41.2': + resolution: {integrity: sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@oxc-parser/binding-android-arm-eabi@0.121.0': resolution: {integrity: sha512-n07FQcySwOlzap424/PLMtOkbS7xOu8nsJduKL8P3COGHKgKoDYXwoAHCbChfgFpHnviehrLWIPX0lKGtbEk/A==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3084,6 +3358,9 @@ packages: peerDependencies: typescript: ^3 || ^4 || ^5 + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -3130,6 +3407,36 @@ packages: '@prisma/get-platform@6.19.3': resolution: {integrity: sha512-xFj1VcJ1N3MKooOQAGO0W5tsd0W2QzIvW7DD7c/8H14Zmp4jseeWAITm+w2LLoLrlhoHdPPh0NMZ8mfL6puoHA==} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.1': + resolution: {integrity: sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.1': + resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} + '@puppeteer/browsers@2.13.1': resolution: {integrity: sha512-zmS4RTK9fbrc++WlAJhxYbfz3IjDeOmkK/CwwbLmk7ydfS9e2CiEeRJHEPvjDVElO/bwXbidwGA37Bsm6LzCnQ==} engines: {node: '>=18'} @@ -3941,6 +4248,12 @@ packages: '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + '@types/pg-pool@2.0.7': + resolution: {integrity: sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng==} + + '@types/pg@8.15.6': + resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==} + '@types/qs@6.15.0': resolution: {integrity: sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==} @@ -4295,6 +4608,11 @@ packages: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + acorn-import-phases@1.0.4: resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} engines: {node: '>=10.13.0'} @@ -4477,6 +4795,10 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + autoprefixer@10.5.0: resolution: {integrity: sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==} engines: {node: ^10 || ^12 || >=14} @@ -5200,6 +5522,9 @@ packages: resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -5685,6 +6010,9 @@ packages: resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} engines: {node: '>=8.0.0'} + fast-copy@4.0.3: + resolution: {integrity: sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -5823,6 +6151,9 @@ packages: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} + forwarded-parse@2.1.2: + resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -6020,6 +6351,9 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + homedir-polyfill@1.0.3: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} @@ -6168,6 +6502,10 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + import-in-the-middle@3.0.1: + resolution: {integrity: sha512-pYkiyXVL2Mf3pozdlDGV6NAObxQx13Ae8knZk1UJRJ6uRW/ZRmTGHlQYtrsSl7ubuE5F8CD1z+s1n4RHNuTtuA==} + engines: {node: '>=18'} + import-local@3.2.0: resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} engines: {node: '>=8'} @@ -6637,6 +6975,10 @@ packages: jose@6.2.3: resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + jpeg-js@0.4.4: resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==} @@ -6922,6 +7264,9 @@ packages: lodash-es@4.18.1: resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -6952,6 +7297,9 @@ packages: long-timeout@0.1.1: resolution: {integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==} + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + lookup-closest-locale@6.2.0: resolution: {integrity: sha512-/c2kL+Vnp1jnV6K6RpDTHK3dgg0Tu2VVp+elEiJpjfS1UyY7AjOYHohRug6wT0OpoX2qFgNORndE9RqesfVxWQ==} @@ -7170,6 +7518,9 @@ packages: engines: {node: '>=10'} hasBin: true + module-details-from-path@1.0.4: + resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} @@ -7238,6 +7589,24 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + nestjs-cls@6.2.0: + resolution: {integrity: sha512-b2Remha7gV5gId3ezjr2tupjqqgYK7/JqjqX6oZ0ZIDFATUggKH1/32+ul2lOe7FepnHasDONDoePuWEE64cug==} + engines: {node: '>=18'} + peerDependencies: + '@nestjs/common': '>= 10 < 12' + '@nestjs/core': '>= 10 < 12' + reflect-metadata: '*' + rxjs: '>= 7' + + nestjs-pino@4.6.1: + resolution: {integrity: sha512-nuARXa0xpdJ1lY2+fgycIQr6H3g0VgqAWNK3xMYjOFcj2DoPETNXj0lV3Y86nRuI7BUfQp5PGiVoZvT4dTWbpQ==} + engines: {node: '>= 14'} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 + pino: ^7.5.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 + pino-http: ^6.4.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 + rxjs: ^7.1.0 + nestjs-prisma@0.27.0: resolution: {integrity: sha512-rCqkBbT+/2/IPdLJL2KD50uR4Rc9X5LFRDvTSPkd2SfGoF3nE3iMQ9as0to8fqU4ipk/7/Y9aFO+WTYUbES0Sg==} peerDependencies: @@ -7371,6 +7740,10 @@ packages: 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'} + on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -7572,6 +7945,17 @@ packages: perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + pg-protocol@1.13.0: + resolution: {integrity: sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==} + + pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -7591,6 +7975,23 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} + pino-abstract-transport@3.0.0: + resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} + + pino-http@11.0.0: + resolution: {integrity: sha512-wqg5XIAGRRIWtTk8qPGxkbrfiwEWz1lgedVLvhLALudKXvg1/L2lTFgTGPJ4Z2e3qcRmxoFxDuSdMdMGNM6I1g==} + + pino-pretty@13.1.3: + resolution: {integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==} + hasBin: true + + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + + pino@10.3.1: + resolution: {integrity: sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==} + hasBin: true + pirates@4.0.7: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} @@ -7861,6 +8262,22 @@ packages: resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} engines: {node: ^10 || ^12 || >=14} + postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + + postgres-bytea@1.0.1: + resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==} + engines: {node: '>=0.10.0'} + + postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + + postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -7895,6 +8312,9 @@ packages: process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + progress@2.0.3: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} @@ -7903,6 +8323,14 @@ packages: resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} engines: {node: '>=10'} + protobufjs@7.5.7: + resolution: {integrity: sha512-NGnrxS/nLKUo5nkbVQxlC71sB4hdfImdYIbFeSCidxtwATx0AHRPcANSLd0q5Bb2BkoSWo2iisQhGg5/r+ihbA==} + engines: {node: '>=12.0.0'} + + protobufjs@8.0.1: + resolution: {integrity: sha512-NWWCCscLjs+cOKF/s/XVNFRW7Yih0fdH+9brffR5NZCy8k42yRdl5KlWKMVXuI1vfCoy4o1z80XR/W/QUb3V3w==} + engines: {node: '>=12.0.0'} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -7956,6 +8384,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -8003,6 +8434,10 @@ packages: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + rechoir@0.8.0: resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} engines: {node: '>= 10.13.0'} @@ -8036,6 +8471,10 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + require-in-the-middle@8.0.1: + resolution: {integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==} + engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'} + require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} @@ -8153,6 +8592,10 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -8327,6 +8770,9 @@ packages: secure-compare@3.0.1: resolution: {integrity: sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==} + secure-json-parse@4.1.0: + resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} + select-hose@2.0.0: resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} @@ -8475,6 +8921,9 @@ packages: resolution: {integrity: sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + sonic-boom@4.2.1: + resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} + sorted-array-functions@1.3.0: resolution: {integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==} @@ -8537,6 +8986,10 @@ packages: resolution: {integrity: sha512-DI7/OuAUD+GMpR6dmu8lliO2Wg5zfeh+/xsdyJZCzd8o5JgFUjCeLsBDuZjIQJdwXS3J0L/uZYrELKYqx+PXog==} engines: {node: '>=8.0'} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -8642,6 +9095,10 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + strtok3@10.3.5: resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} engines: {node: '>=18'} @@ -8765,6 +9222,10 @@ packages: third-party-web@0.29.0: resolution: {integrity: sha512-nBDSJw5B7Sl1YfsATG2XkW5qgUPODbJhXw++BKygi9w6O/NKS98/uY/nR/DxDq2axEjL6halHW1v+jhm/j1DBQ==} + thread-stream@4.0.0: + resolution: {integrity: sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==} + engines: {node: '>=20'} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -9473,6 +9934,10 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} @@ -9668,7 +10133,7 @@ snapshots: '@analogjs/vite-plugin-angular': 2.5.0(@angular/build@21.2.10(@angular/compiler-cli@21.2.12(@angular/compiler@21.2.12)(typescript@5.9.3))(@angular/compiler@21.2.12)(@angular/core@21.2.12(@angular/compiler@21.2.12)(rxjs@7.8.2))(@angular/platform-browser@21.2.12(@angular/common@21.2.12(@angular/core@21.2.12(@angular/compiler@21.2.12)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.12(@angular/compiler@21.2.12)(rxjs@7.8.2)))(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.3)(chokidar@5.0.0)(jiti@2.7.0)(less@4.5.1)(lightningcss@1.32.0)(postcss@8.5.14)(sass-embedded@1.99.0)(tailwindcss@4.3.0)(terser@5.46.2)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.1.5)(yaml@2.8.4))(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) '@angular-devkit/architect': 0.2102.10(chokidar@5.0.0) '@angular-devkit/schematics': 21.2.10(chokidar@5.0.0) - vitest: 4.1.5(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) + vitest: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) '@angular-devkit/architect@0.2102.10(chokidar@5.0.0)': dependencies: @@ -9845,7 +10310,7 @@ snapshots: lmdb: 3.5.1 postcss: 8.5.14 tailwindcss: 4.3.0 - vitest: 4.1.5(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) + vitest: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -11105,6 +11570,18 @@ snapshots: '@gar/promise-retry@1.0.3': {} + '@grpc/grpc-js@1.14.3': + dependencies: + '@grpc/proto-loader': 0.8.1 + '@js-sdsl/ordered-map': 4.4.2 + + '@grpc/proto-loader@0.8.1': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.3.2 + protobufjs: 7.5.7 + yargs: 17.7.2 + '@harperfast/extended-iterable@1.0.3': optional: true @@ -11619,6 +12096,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@js-sdsl/ordered-map@4.4.2': {} + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': dependencies: tslib: 2.8.1 @@ -12700,7 +13179,7 @@ snapshots: tsconfig-paths: 4.2.0 tslib: 2.8.1 vite: 8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4) - vitest: 4.1.5(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) + vitest: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) transitivePeerDependencies: - '@babel/traverse' - '@nx/eslint' @@ -12722,7 +13201,7 @@ snapshots: optionalDependencies: '@nx/eslint': 22.7.1(68aafc8fdac1310e0a96c43f6d4a0bfa) vite: 8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4) - vitest: 4.1.5(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) + vitest: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -12833,6 +13312,308 @@ snapshots: - '@swc/core' - debug + '@opentelemetry/api-logs@0.217.0': + dependencies: + '@opentelemetry/api': 1.9.1 + + '@opentelemetry/api@1.9.1': {} + + '@opentelemetry/configuration@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + yaml: 2.8.4 + + '@opentelemetry/context-async-hooks@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + + '@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/exporter-logs-otlp-grpc@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@grpc/grpc-js': 1.14.3 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-grpc-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.217.0(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-logs-otlp-http@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.217.0 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.217.0(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-logs-otlp-proto@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.217.0 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-metrics-otlp-grpc@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@grpc/grpc-js': 1.14.3 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-metrics-otlp-http': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-grpc-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-metrics-otlp-http@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-metrics-otlp-proto@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-metrics-otlp-http': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-prometheus@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/exporter-trace-otlp-grpc@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@grpc/grpc-js': 1.14.3 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-grpc-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-trace-otlp-http@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-trace-otlp-proto@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-zipkin@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/instrumentation-express@0.65.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-http@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + forwarded-parse: 2.1.2 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-ioredis@0.65.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/redis-common': 0.38.3 + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-nestjs-core@0.63.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-pg@0.69.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.1) + '@types/pg': 8.15.6 + '@types/pg-pool': 2.0.7 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-pino@0.63.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.217.0 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.217.0(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.217.0 + import-in-the-middle: 3.0.1 + require-in-the-middle: 8.0.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/otlp-exporter-base@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + + '@opentelemetry/otlp-grpc-exporter-base@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@grpc/grpc-js': 1.14.3 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.217.0(@opentelemetry/api@1.9.1) + + '@opentelemetry/otlp-transformer@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.217.0 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + protobufjs: 8.0.1 + + '@opentelemetry/propagator-b3@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/propagator-jaeger@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/redis-common@0.38.3': {} + + '@opentelemetry/resources@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/sdk-logs@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.217.0 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/sdk-metrics@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/sdk-node@0.217.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.217.0 + '@opentelemetry/configuration': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/context-async-hooks': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-logs-otlp-grpc': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-logs-otlp-http': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-logs-otlp-proto': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-metrics-otlp-grpc': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-metrics-otlp-http': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-metrics-otlp-proto': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-prometheus': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-trace-otlp-grpc': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-trace-otlp-http': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-trace-otlp-proto': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-zipkin': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/propagator-b3': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/propagator-jaeger': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.217.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-node': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/sdk-trace-node@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/context-async-hooks': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/semantic-conventions@1.40.0': {} + + '@opentelemetry/sql-common@0.41.2(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@oxc-parser/binding-android-arm-eabi@0.121.0': optional: true @@ -13137,6 +13918,8 @@ snapshots: esquery: 1.7.0 typescript: 5.9.3 + '@pinojs/redact@0.4.0': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -13183,6 +13966,29 @@ snapshots: dependencies: '@prisma/debug': 6.19.3 + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.5': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.1 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.1': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.1': {} + '@puppeteer/browsers@2.13.1': dependencies: debug: 4.4.3 @@ -13883,6 +14689,16 @@ snapshots: '@types/parse-json@4.0.2': {} + '@types/pg-pool@2.0.7': + dependencies: + '@types/pg': 8.15.6 + + '@types/pg@8.15.6': + dependencies: + '@types/node': 24.12.3 + pg-protocol: 1.13.0 + pg-types: 2.2.0 + '@types/qs@6.15.0': {} '@types/range-parser@1.2.7': {} @@ -14101,7 +14917,7 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.5(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) + vitest: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) '@vitest/expect@4.1.5': dependencies: @@ -14147,7 +14963,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vitest: 4.1.5(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) + vitest: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) '@vitest/utils@4.1.5': dependencies: @@ -14268,6 +15084,10 @@ snapshots: mime-types: 3.0.2 negotiator: 1.0.0 + acorn-import-attributes@1.9.5(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + acorn-import-phases@1.0.4(acorn@8.16.0): dependencies: acorn: 8.16.0 @@ -14445,6 +15265,8 @@ snapshots: asynckit@0.4.0: {} + atomic-sleep@1.0.0: {} + autoprefixer@10.5.0(postcss@8.5.14): dependencies: browserslist: 4.28.2 @@ -15269,6 +16091,8 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' + dateformat@4.6.3: {} + debug@2.6.9: dependencies: ms: 2.0.0 @@ -15797,6 +16621,8 @@ snapshots: dependencies: pure-rand: 6.1.0 + fast-copy@4.0.3: {} + fast-deep-equal@3.1.3: {} fast-fifo@1.3.2: {} @@ -15960,6 +16786,8 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + forwarded-parse@2.1.2: {} + forwarded@0.2.0: {} fraction.js@5.3.4: {} @@ -16154,6 +16982,8 @@ snapshots: he@1.2.0: {} + help-me@5.0.0: {} + homedir-polyfill@1.0.3: dependencies: parse-passwd: 1.0.0 @@ -16328,6 +17158,13 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-in-the-middle@3.0.1: + dependencies: + acorn: 8.16.0 + acorn-import-attributes: 1.9.5(acorn@8.16.0) + cjs-module-lexer: 2.2.0 + module-details-from-path: 1.0.4 + import-local@3.2.0: dependencies: pkg-dir: 4.2.0 @@ -17117,6 +17954,8 @@ snapshots: jose@6.2.3: {} + joycon@3.1.1: {} + jpeg-js@0.4.4: {} js-library-detector@6.7.0: {} @@ -17438,6 +18277,8 @@ snapshots: lodash-es@4.18.1: {} + lodash.camelcase@4.3.0: {} + lodash.debounce@4.0.8: {} lodash.memoize@4.1.2: {} @@ -17468,6 +18309,8 @@ snapshots: long-timeout@0.1.1: {} + long@5.3.2: {} + lookup-closest-locale@6.2.0: {} lru-cache@10.4.3: {} @@ -17676,6 +18519,8 @@ snapshots: mkdirp@3.0.1: {} + module-details-from-path@1.0.4: {} + mrmime@2.0.1: {} ms@2.0.0: {} @@ -17737,6 +18582,20 @@ snapshots: neo-async@2.6.2: {} + nestjs-cls@6.2.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2): + dependencies: + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) + reflect-metadata: 0.2.2 + rxjs: 7.8.2 + + nestjs-pino@4.6.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.3.1)(rxjs@7.8.2): + dependencies: + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + pino: 10.3.1 + pino-http: 11.0.0 + rxjs: 7.8.2 + nestjs-prisma@0.27.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@prisma/client@6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3))(chokidar@5.0.0)(prisma@6.19.3(typescript@5.9.3)): dependencies: '@angular-devkit/core': 13.3.11(chokidar@5.0.0) @@ -17996,6 +18855,8 @@ snapshots: ohash@2.0.11: {} + on-exit-leak-free@2.1.2: {} + on-finished@2.4.1: dependencies: ee-first: 1.1.1 @@ -18283,6 +19144,18 @@ snapshots: perfect-debounce@1.0.0: {} + pg-int8@1.0.1: {} + + pg-protocol@1.13.0: {} + + pg-types@2.2.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.1 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + picocolors@1.1.1: {} picomatch@2.3.2: {} @@ -18294,6 +19167,49 @@ snapshots: pify@4.0.1: optional: true + pino-abstract-transport@3.0.0: + dependencies: + split2: 4.2.0 + + pino-http@11.0.0: + dependencies: + get-caller-file: 2.0.5 + pino: 10.3.1 + pino-std-serializers: 7.1.0 + process-warning: 5.0.0 + + pino-pretty@13.1.3: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 4.0.3 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 3.0.0 + pump: 3.0.4 + secure-json-parse: 4.1.0 + sonic-boom: 4.2.1 + strip-json-comments: 5.0.3 + + pino-std-serializers@7.1.0: {} + + pino@10.3.1: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 3.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: 4.0.0 + pirates@4.0.7: {} piscina@5.1.4: @@ -18552,6 +19468,16 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postgres-array@2.0.0: {} + + postgres-bytea@1.0.1: {} + + postgres-date@1.0.7: {} + + postgres-interval@1.2.0: + dependencies: + xtend: 4.0.2 + prelude-ls@1.2.1: {} prettier@3.8.3: {} @@ -18582,6 +19508,8 @@ snapshots: process-nextick-args@2.0.1: {} + process-warning@5.0.0: {} + progress@2.0.3: {} promise-retry@2.0.1: @@ -18589,6 +19517,36 @@ snapshots: err-code: 2.0.3 retry: 0.12.0 + protobufjs@7.5.7: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.1 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.1 + '@types/node': 24.12.3 + long: 5.3.2 + + protobufjs@8.0.1: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.1 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.1 + '@types/node': 24.12.3 + long: 5.3.2 + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -18658,6 +19616,8 @@ snapshots: queue-microtask@1.2.3: {} + quick-format-unescaped@4.0.4: {} + range-parser@1.2.1: {} raw-body@2.5.3: @@ -18713,6 +19673,8 @@ snapshots: readdirp@5.0.0: {} + real-require@0.2.0: {} + rechoir@0.8.0: dependencies: resolve: 1.22.12 @@ -18744,6 +19706,13 @@ snapshots: require-from-string@2.0.2: {} + require-in-the-middle@8.0.1: + dependencies: + debug: 4.4.3 + module-details-from-path: 1.0.4 + transitivePeerDependencies: + - supports-color + require-main-filename@2.0.0: {} requires-port@1.0.0: {} @@ -18913,6 +19882,8 @@ snapshots: safe-buffer@5.2.1: {} + safe-stable-stringify@2.5.0: {} + safer-buffer@2.1.2: {} sass-embedded-all-unknown@1.99.0: @@ -19055,6 +20026,8 @@ snapshots: secure-compare@3.0.1: {} + secure-json-parse@4.1.0: {} + select-hose@2.0.0: {} selfsigned@2.4.1: @@ -19247,6 +20220,10 @@ snapshots: ip-address: 10.2.0 smart-buffer: 4.2.0 + sonic-boom@4.2.1: + dependencies: + atomic-sleep: 1.0.0 + sorted-array-functions@1.3.0: {} source-map-js@1.2.1: {} @@ -19318,6 +20295,8 @@ snapshots: image-ssim: 0.2.0 jpeg-js: 0.4.4 + split2@4.2.0: {} + sprintf-js@1.0.3: {} ssri@13.0.1: @@ -19418,6 +20397,8 @@ snapshots: strip-json-comments@3.1.1: {} + strip-json-comments@5.0.3: {} + strtok3@10.3.5: dependencies: '@tokenizer/token': 0.3.0 @@ -19565,6 +20546,10 @@ snapshots: third-party-web@0.29.0: {} + thread-stream@4.0.0: + dependencies: + real-require: 0.2.0 + through@2.3.8: {} thunky@1.1.0: {} @@ -19919,7 +20904,7 @@ snapshots: terser: 5.46.2 yaml: 2.8.4 - vitest@4.1.5(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)): + vitest@4.1.5(@opentelemetry/api@1.9.1)(@types/node@24.12.3)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(jsdom@29.1.1)(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)): dependencies: '@vitest/expect': 4.1.5 '@vitest/mocker': 4.1.5(vite@8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4)) @@ -19942,6 +20927,7 @@ snapshots: vite: 8.0.11(@types/node@24.12.3)(esbuild@0.27.3)(jiti@2.7.0)(less@4.5.1)(sass-embedded@1.99.0)(sass@1.99.0)(terser@5.46.2)(yaml@2.8.4) why-is-node-running: 2.3.0 optionalDependencies: + '@opentelemetry/api': 1.9.1 '@types/node': 24.12.3 '@vitest/coverage-v8': 4.1.5(vitest@4.1.5) '@vitest/ui': 4.1.5(vitest@4.1.5) @@ -20211,6 +21197,8 @@ snapshots: xmlchars@2.2.0: {} + xtend@4.0.2: {} + y18n@4.0.3: {} y18n@5.0.8: {}