* fix(security): neutralize spreadsheet formulas in CSV exports
GHSA-7xp5-j564-4752 (medium): exported cells were written verbatim, so a stored
value beginning with = + - or @ executed as a formula when a colleague opened the
export in Excel or Sheets. A shared encoder in @gauzy/utils prefixes an
apostrophe to any cell starting with a formula trigger (including the full-width
forms), leaves strictly numeric values alone, and is reversed on import so an
export/import round-trip stays byte-exact. Every field is now quoted, which also
stops a bare CR inside a value from starting a new spreadsheet row, and the
invoice CSV in the web app gets real RFC 4180 quoting instead of JSON.stringify.
GHSA-86mw-2crg-vmhc residuals (low): the public invite routes are throttled, the
shipped compose files no longer trust a forwarded client IP while publishing the
API port directly, and RequestContext.currentIp() resolves the client address the
same way the throttler does instead of reading a spoofable header.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* chore(cspell): add the new vocabulary and use US spellings
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(export-import): decode CSV cells only for archives we marked
The import side reversed the spreadsheet-formula escape on every parsed row,
but an uploaded ZIP is not necessarily one this server wrote: it can be a dump
from an older Gauzy, a filled-in `/export/template`, or a CSV set built by
external tooling. For those, un-escaping is data loss — a legitimate value such
as `'=notes` was persisted as `=notes`, silently. Both review bots flagged this
as the one thing blocking the merge, and they were right: the decoder had no way
to tell "we escaped this" from "somebody else wrote this".
A data export now carries a `gauzy-export.json` marker at the archive root
(format, version, `spreadsheetSafeCells`), written by `exportTables` and
`exportSpecificTables`. `ImportService` resolves that marker once per import and
decodes rows only when it is present and recognized; anything else is imported
byte for byte as it was parsed. `/export/template` is deliberately NOT marked —
an operator fills it in by hand, so nothing in it was ever escaped. The manifest
reader is defensive about an attacker-supplied file: missing, oversized,
malformed, a foreign format or a newer version all mean "do not decode".
The invoice/payment CSV builder no longer has a path that skips encoding: a
pre-joined header line used to be written through verbatim, and it was the only
value in the file that reached disk unquoted and un-neutralized. `buildCsv` and
`generateCsv` now declare `headers: string[]` (both callers already pass one),
and a stray string from an untyped caller is split and encoded rather than
trusted.
Tests: `import.service.spec.ts` imports the same escaped CSV with and without a
marker and asserts the apostrophe survives when unmarked (reverting the gate
fails those 5 tests); `export.service.spec.ts` asserts the data archive carries
the marker and the template archive does not.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
`{"constructor": null}` is valid JSON, so any parsed payload can carry an own
`constructor` that is null or undefined. Reading `.name` on it throws exactly
like the null-prototype case this branch fixes, and the crash is reachable from
real input: `parseObject`, `deepClone` and `deepMerge` all call
`isClassInstance`, and `{"constructor":null}` survives `JSON.parse` intact.
Read the constructor into a local first and treat null/undefined as plain data.
Behaviour is unchanged for every input that did not already throw - checked
against the pre-fix implementation across 27 object shapes (plain literals,
null-prototype objects, class instances, Date/Map/Set/RegExp, arrays,
primitives, nested values); only the previously-throwing shapes changed, and
all of them now answer `false`.
Adds test harnesses for tenant isolation, TypeORM/MikroORM parity, persistence invariants and idempotency; startup validation for DB config; Nx plugin/core boundary rules; a fresh-database migration smoke test; and a correlation id carried from HTTP requests into docs queue jobs and logs.
Testing (packages/core/src/lib/core/testing):
- tenant-isolation: an in-memory tenant-aware repository, fixtures and strict assertions (a non-empty page, every row in the caller's tenant). Applied to EmployeeService and OrganizationProjectService.
- orm-conformance and persistence-invariants: suites that run the same checks under TypeORM and MikroORM (run-both-orms.sh uses yarn nx).
- idempotency: assertion helpers and specs for token cleanup (positive control), employee notifications and the Zapier timer webhook.
- database/migration-smoke.spec.ts: runs the full migration chain on a fresh better-sqlite3 database. It is excluded from the default core jest run; run it with `nx run core:test-migration-smoke`.
Idempotency:
- EmployeeNotificationService.create() takes an opt-in `absorbRedelivery`. With it set, an identical unread, unarchived notification under 60 s old (same receiver, entity, type, sender, title and message) is returned instead of inserted, and a missing key or a failed lookup inserts as usual. The event handler does not enable it (the in-process EventBus never redelivers), so every caller inserts one row per event as before.
- ZapierWebhookService skips resending a webhook that already succeeded for the same subscription, action and time log within 5 minutes. The key is reserved while in flight, failed deliveries stay retryable, pruning stops at the first unexpired entry, and the cache is capped at 10,000 entries.
Config (packages/config):
- An unknown DB_TYPE fails fast with the list of supported values; an empty DB_TYPE still means better-sqlite3; mongodb throws an Error.
- Pool and timeout variables are parsed with Number.parseInt semantics, only for postgres and mysql. They throw only where tarn already refused to start and warn otherwise. SQLite ignores them and still prints the startup values.
Observability:
- RequestContextMiddleware accepts an inbound x-correlation-id of 1-128 visible ASCII characters (otherwise it generates a UUIDv4) and echoes it on the response. CORS allows and exposes X-Correlation-Id. RequestContext.currentCorrelationId() is added.
- The docs queue carries the correlation id through job payloads (including bulk reindex) into pipeline outcome, error, dead-letter and enqueue-failure logs.
Boundaries and build:
- Every project gets a type tag. The ESLint depConstraints stop type:core depending on plugins, and plugins may depend only on core, shared libs and the known extension points (ai-chat, job-proposal, integration-ai, job-*-ui).
- core declares @gauzy/scheduler (package.json and implicitDependencies); the webapp Dockerfile copies scheduler's package.json.
- The integration-zapier jest config can import @gauzy/core (transformIgnorePatterns, allowJs, isolatedModules).
- Fixes the stale @nrwl/nx eslint-disable id in the e2e roles-permissions steps and the broken @gauzy/core mock in the docs document-scope spec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three follow-ups from the independent verification of the connection-level
SSRF guard.
The private-address predicate in @gauzy/utils treated several special-purpose
ranges as public: benchmarking space 198.18.0.0/15 (a common cluster CIDR),
the IETF and documentation ranges, multicast, 240.0.0.0/4, deprecated
site-local fec0::/10, the NAT64 local-use prefix 64:ff9b:1::/48 and the
deprecated IPv4-compatible ::a.b.c.d form, so [::7f00:1] passed the literal
check. They are now refused. The shared predicate is also used by the core
SSRF agent and the Make.com, Zapier and Ever Async integrations; none of their
legitimate destinations sits in these ranges.
The validating lookup's promise chain now ends in a catch. If Node's connect
callback ever threw synchronously, the throw would otherwise become an
unhandled rejection, which terminates the process on Node 24.
An empty constructor in a spec mock tripped the no-empty-function lint rule.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Addresses the review findings on the GitHub webhook and AI-provider SSRF fix.
The DNS pre-flight in ssrfSafeFetch now fails closed: only a definitive
non-existence answer (ENOTFOUND and equivalents) is let through, every other
resolver failure is refused. Verdicts are no longer cached, IP literals skip
the lookup, and the lookup honours the request AbortSignal so a stalled
resolver cannot outlive the dictation or catalogue timeout. The successful
transcription body is now read under a 4 MiB byte budget instead of being
buffered whole by response.json().
GAUZY_AI_CHAT_ALLOW_PRIVATE_BASE_URLS now governs tenant-entered base URLs
only. The new isPrivateAiProviderEndpointAllowed(credentials) helper allows
operator environment values and built-in local defaults, and the twelve
catalogue and speech call sites across nine provider plugins pass it.
A resolver seam is threaded through fetchCatalogueJson and the speech helpers
and the provider specs stub dns.lookup, so the suites no longer depend on live
DNS and the raised testTimeout in five jest configs is removed.
isPrivateOrLoopbackHost in @gauzy/utils now recognises NAT64 (64:ff9b::/96)
and 6to4 (2002::/16) addresses that embed a private IPv4 address, which also
covers the Make.com and Zapier webhook guards.
The webhook receiver keys the HMAC with the configured secret verbatim and
trims only to detect a blank one. Test fixtures for the secret are generated
at runtime, the raw-bytes test now really distinguishes raw bytes from a
re-serialization, and the credential service gains tests for the
null-clear and omitted base URL branches.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
No lint invocation in this repo could reach a single file. `nx run-many -t lint --all` failed for
93 of 93 projects, and no CI workflow runs lint, so nothing ever noticed. Two independent bugs,
either of which alone was fatal.
1. The root `eslint.config.js` was `module.exports = new FlatESLint({ overrides: [] })`, importing
a `FlatESLint` class from `@nx/eslint-plugin-nx`. That could never have worked: a flat config
must export an array, and no Nx package has ever exported such a class. `@nx/eslint-plugin-nx`
is the beta-only predecessor NAME of `@nx/eslint-plugin` — the repo declared both, the real one
at ^22.5.2 and this one pinned at 16.0.0-beta.1. The v16 beta drags a nested `@nx/devkit@16`
that expects an `nx` internal path nx@22 no longer ships, so every `eslint` invocation died
with `Cannot find module 'nx/src/utils/typescript'`.
2. All 41 project configs did `[...require('../../.eslintrc.json')]`. That file is a JSON object,
so the spread threw `TypeError: baseConfig is not iterable` — a different failure, on the path
`nx lint <project>` actually takes. `packages/mcp-server` also had the wrong depth.
Changes: remove `@nx/eslint-plugin-nx`, add `typescript-eslint@^8.40.0` (the only genuinely
missing package — `@nx/eslint-plugin`'s flat configs require it unconditionally); rewrite the root
config as a real flat array shaped like Nx 22's own generator output, with real `ignores`
replacing the legacy `"ignorePatterns": ["**/*"]` that disabled linting workspace-wide; repoint
all 41 project configs at the root flat config, dropping the FlatCompat bridge the 12 `.cjs` ones
used; disable the deprecated `@typescript-eslint/no-empty-interface`, which Nx's presets still
enable alongside its v8 replacement `no-empty-object-type` and so double-reported every
occurrence; and re-enable `no-dupe-keys`, `no-dupe-class-members`, `no-dupe-args` and
`no-unreachable`, which typescript-eslint's `eslint-recommended` overlay turns off on the grounds
that `tsc` reports them — no CI job here runs `tsc --noEmit`, and a duplicate key in
`packages/core/jest.config.ts` has already silently changed behaviour once.
The legacy `.eslintrc.json` files are deliberately KEPT: `.codacy/codacy.yaml` pins eslint@8.57.0,
which does read them.
The guardrail is proven, not assumed — against the real historical bug:
packages/core/jest.config.ts
29:2 error Duplicate key 'transformIgnorePatterns' no-dupe-keys
Findings are REPORTED, NOT FIXED (a separate job): 8,887 files linted, 2,290 with problems,
2,649 errors / 6,110 warnings, zero parse errors. Lint should not become a required check until
that backlog is triaged.
Verified: packages/core 56/56 suites and 612/612 tests; build-monorepo-root, build-api, build-libs
and build-web all green; all 42 configs load; `nx lint <project>` now runs and reports instead of
crashing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- utils (isPrivateOrLoopbackHost): normalize a trailing root dot (localhost.), detect IPv4-mapped
IPv6 in BOTH dotted (::ffff:127.0.0.1) and hex (::ffff:7f00:1) forms, and match the full fe80::/10
link-local and fc00::/7 unique-local ranges via first-hextet masking instead of crude string
prefixes (CodeRabbit/Greptile).
- make-com webhook: add an SSRF-safe HTTPS agent whose DNS resolver refuses connections to
private/loopback/link-local resolved IPs, and use it for the outbound POST. This closes
DNS-rebinding / hostname-based SSRF at connection time (no TOCTOU gap) on top of the literal
store-time/request-time checks (CodeRabbit Critical / Greptile P1).
- make-com-api: validate the stored zone once via getValidatedZone() and reuse it in
getZoneBaseUrl/getZone/getSetupStatus so read paths and isComplete stay consistent and never
expose an out-of-allowlist zone (CodeRabbit).
- cspell: allowlist security vocabulary and identifiers.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- image-asset: add content-based validation. The multer fileFilter only inspects the
client-controlled MIME type/filename (spoofable), so re-check the stored bytes and reject
markup (SVG/XML/HTML/XHTML) that would execute as stored XSS from /public. The rejected file is
deleted because /public serves from disk regardless of the DB record (flagged by CodeRabbit/Cubic).
- deep-clone: only skip __proto__ (not constructor/prototype). Cloning must preserve ordinary own
data keys named constructor/prototype; the dangerous recursion only exists in deepMerge, which
still blocks all three (flagged by Cubic).
- search handler: reuse the exported PLUGIN_SORTABLE_FIELDS / PLUGIN_SORT_DIRECTIONS from the DTO
instead of duplicating the allowlist, so validation and the SQL sink cannot drift.
- cspell: allowlist security vocabulary and advisory-id fragments.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- make-com: validate the `zone` against the MAKE_COM_ZONES allowlist via a SetZoneDTO
(`@IsIn`) + `@UseValidationPipe`, and re-check it before building the API base URL, so a
tenant can no longer inject an arbitrary host into `https://${zone}.make.com/...`
(GHSA-vcwx-qh95-54g6).
- make-com: validate the stored `webhookUrl` with an SSRF egress guard at store time AND
again before each outbound POST, rejecting non-HTTPS, embedded credentials,
loopback/private/link-local hosts and the cloud-metadata IP (GHSA-534m-c6mh-mp98).
- utils: add a reusable, browser-safe `getUnsafeOutboundUrlReason` /
`isPrivateOrLoopbackHost` helper, used by both integrations.
- zapier: apply the same egress guard UNCONDITIONALLY (the private-IP/loopback block
previously ran only when `NODE_ENV === 'production'`, leaving dev/staging unprotected).
Note: literal host/IP checks only; DNS-rebinding / hostname->private-IP hardening (resolve
and re-check at request time) is a recommended follow-up.
Refs: GHSA-vcwx-qh95-54g6, GHSA-534m-c6mh-mp98
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- registry: validate plugin search/category `sortBy` & `sortDirection` against an
explicit allowlist (`@IsIn`) instead of `@IsString`, closing the unauthenticated
ORDER BY SQL injection (GHSA-xqcf-j9jr-7w59). A case-normalizing `@Transform`
keeps legacy `asc`/`desc` clients working, and the query handler also clamps the
sort inputs as defense-in-depth.
- utils: filter `__proto__`/`constructor`/`prototype` in `deepMerge` and
`deepClone` to prevent prototype pollution (GHSA-qfc6-v3g6-rxf8), and give
`POST /auth/email/verify/resend-link` a validated DTO + `whitelist` pipe.
- core: reject SVG and other non-raster uploads on the image-asset endpoint via a
multer `fileFilter` (passed through `LazyFileInterceptor`) to stop stored XSS
from `/public/<key>` (GHSA-p334-cm7f-php5).
Refs: GHSA-xqcf-j9jr-7w59, GHSA-qfc6-v3g6-rxf8, GHSA-p334-cm7f-php5
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(utils): parse env variables with fallback value
* fix(pages): use `pages.routes` instead of `pages-routing.module`
* fix(ui-core): base nav menu standlone component & improve menu category
* fix(core): update `tenant-aware-crud.service` to support save many method without checking tenant
* fix(core): update `task-metadata.service` for execute tenant update tasks
* Apply suggestion from @greptile-apps[bot]
* Apply suggestion from @greptile-apps[bot]
* Apply suggestion from @greptile-apps[bot]
* Apply suggestion from @greptile-apps[bot]
* Apply suggestion from @greptile-apps[bot]
* Apply suggestion from @greptile-apps[bot]
* Apply suggestion from @greptile-apps[bot]
* fix(ui-auth): update auth APIs service methods
* Apply suggestion from @greptile-apps[bot]
* Apply suggestion from @greptile-apps[bot]
* Apply suggestion from @greptile-apps[bot]
* fix(ui-core): build for tooltip directive
* Apply suggestion from @greptile-apps[bot]
* Apply suggestion from @greptile-apps[bot]
* Apply suggestion from @greptile-apps[bot]
* @rahul-rocket chore(deps): chore(deps): bump @angular/core from ^20.2.4 to 21.1.2
* fix(ui): update missing jest.preset.js
* fix(nx-migrations): migrate nx from 21.5.1 to 22.4.4
* chore(deps): bump jest-preset-angular to 16.0.0
* chore(deps): bump @nebular/* packages to 17.0.0 for Angular 21 compatibility
* chore(deps): upgrade all packages to Angular 21 and compatible dependencies
* chore(deps): upgrade all packages to Angular 21 and compatible dependencies
* fix(nx-migrations): migrate nx from 21.5.1 to 22.4.4
* Update yarn.lock
* Update yarn.lock
* fix(nx-migrations): migrate nx from 21.5.1 to 22.4.4
* fix(nx-migrations): migrate nx from 21.5.1 to 22.4.4
Replace 'jest-preset-angular/setup-jest' imports with the new 'setupZoneTestEnv' function.
* @nx/jest: replace-removed-matcher-aliases-v22-3
Replace removed matcher aliases in Jest v30 with their corresponding matcher
* chore(deps): @angular/common and @angular/core peerDependencies to ^21.1.0
* Update package.json
* fix(nx-migrations): migrate nx from 21.5.1 to 22.4.4
* chore(deps): bump @nebular/theme from ^16.0.0 to ^17.0.0
* chore(deps): upgrade all packages to Angular 21
* chore(deps): upgrade all packages to Angular 21
* fix(build): update helmet import to support 8.x default export
* fix(build): resolve TypeScript errors and improve code quality
- Fix TemplateRef type conflicts caused by duplicate @angular/core packages (ngx-permissions)
- Change moment imports from namespace to default imports for ESM compatibility
- Convert constructor injection to inject() function in multiple components
- Add OnPush change detection strategy to WindowLayoutComponent
- Make CountdownConfirmationComponent standalone
- Update LayoutWithDraggableObject to use any[] for draggableObject type
* fix(build): fix moment & timezone namespace packages
* fix(build): add jest config for missing packages
* chore(deps): bump swiper from 8.3.1 to 12.1.0
* fix(build): update swiper module and syntax
* Update time-tracking.component.ts
* chore(deps): downgrade `node-polyfill-webpack-plugin` from 4.1.0 to 1.1.4
* fix(deps): resolve browserslist "Unknown version 143 of and_chr" error
Add caniuse-lite and browserslist to yarn resolutions to force all
* fix(nx-migrations): migrate nx from 21.5.1 to 22.4.4
* fix(deps): standardize Angular 21.0.0 versions across all packages and fix compatibility issues
- Fix @angular/* packages to use exact version 21.0.0 (remove caret ^) across all apps, packages, and plugins
- Add @angular/cdk resolution to 21.0.0 to force consistent version
* fix(build): `ui-config` replace env files module issue
* fix(build): `ui-config` replace env files module issue
* fix(build): replace all TemplateRef<HTMLElement> with TemplateRef<any>
* Update package.json
* Update apps\agent\tsconfig.json
* chore(deps): upgrade packages to latest version
* Update yarn.lock
* Update yarn.lock
* fix(build): apply AI suggestion by bot agent reviewers
* fix(build): apply AI suggestion by bot agent reviewers
* fix(nx-migrations): migrate nx from 21.5.1 to 22.4.4
* chore(deps): bump @nestjs/common and @nestjs/core to 11.1.14
* fix(build): replace all TemplateRef<HTMLElement> with TemplateRef<any>
* fix(plugins): apply AI suggestion by bot agent reviewers
* Update yarn.lock
* chore(deps): bump packages
* Update yarn.lock
* chore(deps): bump packages
* chore(deps): bump packages
* fix(plugins): replace 'jest-preset-angular/setup-jest' imports with the new 'setupZoneTestEnv'
* fix(plugins): apply AI suggestion by bot agent reviewers
* fix(cspell): typo spelling :-)
* fix(plugins): apply AI suggestion by bot agent reviewers
* fix: fontawesome icon change version to FA 7
* refactor(ui-core): migrate dashboard directives to standalone
* refactor(ui-core): migrate pipes/directives to standalone
* fix(plugins): apply AI suggestion by bot agent reviewers
* fix(plugins): apply AI suggestion by bot agent reviewers
* chore(deps): bump packages
* refactor(ui-core): migrate directives to standalone
* fix(plugins): apply AI suggestion by bot agent reviewers
---------
Co-authored-by: Ruslan Konviser <evereq@gmail.com>
Co-authored-by: syns2191 <sutralian@gmail.com>
* chore(nx): migrate @nx/workspace to version 20.3.0
* chore(material): run migration-v19 for Angular Material update
* chore(packages): run explicit-standalone-flag migration for Angular v19
* chore(deps): downgrade TypeScript to 5.5.4 for Angular compatibility
* chore(deps): bump Angular ESLint dependencies to version 19
* chore(deps): bump @ng-select/ng-select to version 14.1.0
* chore(deps): bump @commitlint packages to latest versions
* fix(cspell): typo spelling :-)
* chore(packages): migrate initializers to new provider functions
* chore(deps): update the @angular/cli package version to ~19.0.0
* chore(deps): update packages to support Angular v19
* chore(packages): migrate initializers to new provider functions
* fix: correct Sentry.TraceService injection in AppInitializer
* Update yarn.lock
* Update yarn.lock
* fix: update yarn.lock
* fix(cspell): typo spelling :-)
* fix: update yarn.lock
* chore(deps): bump @angular/common to version 19.0.0
* chore(nx): migrate @nx/workspace to version 20.4.2
* chore(deps): update yarn.lock
* chore(nx): migrate @nx/workspace to version 20.4.4
* chore(deps): bump @angular/core from 19.1.5 to 19.1.6
* chore(deps): upgrade @nebular/auth and @nebular/theme to v15
- Upgrade @nebular/auth from ^14.0.2 to ^15.0.0
- Upgrade @nebular/theme from ^14.0.2 to ^15.0.0
* chore(deps): bump @angular-slider/ngx-slider from ^18.0.0 to ^19.0.0
* chore(deps): bump ngx-page-scroll and ngx-page-scroll-core to v14
- Bump ngx-page-scroll from ^13.0.0 to ^14.0.0
- Bump ngx-page-scroll-core from ^13.0.0 to ^14.0.0
* chore(deps): bump ngx-permissions from ^17.1.0 to ^19.0.0
* chore(deps): bump @ng-select/ng-select from ^14.1.0 to ^14.2.2
* chore(deps): bump @fortawesome/angular-fontawesome from 0.15.0 to 1.0.0
* fix: desktop build (make component standalone disabled)
* chore(deps): bump @angular/core from 18.2.12 to 19.1.6
* chore(nx): migrate @nx/workspace to version 20.8.0
* chore(deps): bump ng2-file-upload to version ^8.0.0
* chore(deps): bump @angular/core from 19.1.6 to 19.2.7
* chore(deps): bump @fullcalendar/core from ^6.1.15 to ^6.1.17
* chore(deps): bump @angular-eslint packages to v19.3.0
* fix: add `standalone: false` to angular components
* chore(deps): downgrade @angular-builders/custom-webpack from v19.0.1 to v18.0.0
* chore(deps): bump angular2-smart-table from ^3.5.0 to ^3.6.1
* refactor(styles): replace @import with @use for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* chore(deps): bump @angular/core from 19.0.0 to 19.2.0
* chore(deps): updated dependencies for `@fullcalendar/angular`
* fix(cspell): typo spelling :-)
* Revert "chore(deps): updated dependencies for `@fullcalendar/angular`"
This reverts commit 4b34d72071.
* chore(deps): switch @angular/* to ^19.2.7
* fix: revert nx migrations.json
* Revert "chore(deps): switch @angular/* to ^19.2.7"
This reverts commit edd9105c51.
* fix: align @angular/cdk version with @angular/core version
* chore(deps): bump @angular-builders/custom-webpack from 18.0.0 to 19.0.1
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* refactor(styles): replace `@import` with `@use` for SCSS module
* chore(deps): bump typescript from 5.5.4 to ^5.8.3
* fix(server-dashboard): remove redundant nullish coalescing from autoStart check
* fix: add suggestions from greptile-apps bot review
* fix: add suggestions from greptile-apps bot review
Moves the `isJSON` utility function from `desktop-lib` to the shared `@gauzy/utils` package to avoid code duplication and promote reusability.
Removes the now redundant `util.ts` file from `desktop-lib`.