Stage

Merged
EV
9d ago
+1085540-33971

PR

Please note: we will close your PR without comment if you do not check the boxes above and provide ALL requested information.



Summary by cubic

Promotes stage to develop: runtime, core, tasks and desktop move to Node 26.11.1 with current major versions of Angular, NestJS, Electron, Sentry, yargs, jimp, node-fetch, envalid and simple-git. Lands the Ever Works integration, the Inbox plugin, 16 commerce plugins, and report-catalogue authoring, plus new CI gates, desktop/app fixes and a request-path performance pass; the two new plugins and report authoring are off unless their env switch is on.

Ever Works, Inbox and commerce

  • @gauzy/plugin-integration-ever-works (on with EVER_WORKS_ENABLED=true): resumable two-way sync of teams, projects, tasks, ideas, goals and inbox items, lease-fenced on every Gauzy write and per-side snapshotted so lossy values never flap; deterministic Docs Markdown ↔ TipTap conversion that keeps Gauzy's edit as a conflict version when both sides changed; a connect wizard, per-mapping settings, and a mock-server test.
  • @gauzy/plugin-inbox (on with GAUZY_INBOX_ENABLED=true): inbox items with per-recipient read/archive/snooze state, provider accounts (removal and mailbox attach share a per-account lock), mailboxes with custom-domain TXT verification and auto-provisioning, and the resend/postmark/mailgun/sendgrid/ses reference providers with signed webhooks and SSRF-safe downloads. A Cloudflare Email Worker is the platform receiver; the inbound pipeline threads, sanitizes and quarantines mail; an agent mail bridge mirrors a mailbox read-only; a GraphQL mirror and /pages/inbox, /pages/inbox/mailbox and Settings → Inbox pages serve it, including DNS records and per-mailbox Ever Works agent attachment.
  • Commerce: cart line prices, delivery rates and tax categories resolve server-side from the pricing, shipping and catalogue packages (a stated price, rate or category is ignored and checkout re-prices every line), checkout claims the cart and keeps its discounts and taxes on the order, and a child cart write publishes the cart's ETag. Promotion usage is reserved against the customer's live redemptions before the order row and released on a failed checkout or cancel; creating a promotion that publishes a discount needs PROMOTIONS_EDIT. An authorising payment writes its payment row and feeds the order's ledger (one payment fact is one ledger row, enforced by a unique index), completion is retried on a lost race, refunds serialize under the order's lock, and refunds carry the caller's idempotency key so a retry or resumed claim finds its refund instead of paying again. REST hard deletes scope by organization, promotion counters/coupon codes/campaign budgets refuse writes that would change their effect, a subscription-item correction can't move its line, an undo can withdraw a period-end cancellation, a gift card's PIN is stored as a keyed HMAC digest, the subscription calendar waits for an invoiced cycle's payment, every organization gets a SELLER_PAYOUT numbering series, a settlement is recorded OPEN and an offering created DRAFT, and an order's placed lines carry the rights each grants. GraphQL/rest parity is enforced: cart/order/inventory/fulfillment writes stamp the caller's organization, methodTokens is permission-gated, the seller guard reads input.sellerId, openPaymentSession requires a valid providerId, enum-validated strings are refusals GraphQL can carry, and REST-only order/returns writes are recorded in the parity gate.
  • Security: webhook SSRF blocked, canonical t= signatures only, per-client GraphQL throttling, local storage keys cannot escape root, access tokens carry no role permission list by default (the API loads it from the database per request), every PermissionsEnum value gains a label in every language, and JWT lookups answer 503 instead of 401 when the database is unreachable so valid tokens aren't dropped during a DB outage.

Platform, performance, desktop and CI

  • Performance: libuv threadpool defaults to 16 threads, the JWT path loads the caller in one round trip with concurrent claim lookups, tenant-scoped reads use an EXISTS instead of a join, redundant relation-id loaders are skipped, passport verifications are reported once, Redis cache reads are bounded by a timeout, and LOG_LEVEL is honored.
  • Desktop: timer job queue, active-only screenshot fallback by display index, macOS login items, shared token refresh so concurrent 401s share one refresh, and queued rows from a signed-out user are rejected. App/API: no nested return URL or skeleton hang on a stale session, a failed auth check opens the sign-in form, verified-email matching for GitHub/Facebook, and integration-tenant updates reaching only their org.
  • Deployment: Dockerfiles run Node 26.11.1 and copy vendored packages and plugin manifests; docker-compose.yml adds a worker container; k8s gain API probes, a 2 GiB-fitting heap and move Documents processing to the worker; nginx serves index.html uncached; Sentry keeps pre-upgrade data-collection defaults and production builds ship no source maps; Jest splits --experimental-vm-modules between NestJS and Angular projects.
  • New workflows (Upgrade Test, Docker Build Check, GraphQL Schema, desktop-e2e Playwright) verify migrations on develop's data, image builds, schema non-breakingness and packaged apps; the schema gate reads flag-gated plugins' SDL so the Inbox mirror's fields stay bound; the egress audit also covers the idle web app and connection module. Favorites extend to more entities, global search writes each organization's rows under its own definition (an id-scoped reindex stays in the caller's tenant), and PLATFORM-EXTENSIONS.md records the known unfixed defects from an external commerce review.