Stage
Merged
EV
9d ago+1085540+1085540+0123456789012345678901234567890123456789012345678901234567890123456789-33971-33971-01234567890123456789012345678901234567890123456789
PR
- Have you followed the contributing guidelines?
- Have you explained what your changes do, and why they add value?
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 withEVER_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 withGAUZY_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/mailboxand 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 aSELLER_PAYOUTnumbering 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,methodTokensis permission-gated, the seller guard readsinput.sellerId,openPaymentSessionrequires 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), everyPermissionsEnumvalue 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_LEVELis 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.ymladds aworkercontainer; k8s gain API probes, a 2 GiB-fitting heap and move Documents processing to the worker; nginx servesindex.htmluncached; Sentry keeps pre-upgrade data-collection defaults and production builds ship no source maps; Jest splits--experimental-vm-modulesbetween 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.mdrecords the known unfixed defects from an external commerce review.