Skip to content

Release: develop → stage (2026-11-01: Ever Connect identity, billing fences, Ever Works inbox push, deps, CI fixes) - #11625

Merged
evereq merged 520 commits into
stagefrom
develop
Nov 2, 2026
Merged

evereq merged 520 commits into
stagefrom
develop

Conversation

@evereq

@evereq evereq commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Promotes develop (7da5a66804) to stage as a merge commit. Owner request 2026-11-01: get every open PR reviewed and merged to develop, then cascade to stage and stage-apps for manual testing.

Merged to develop today (all AI-bot threads fixed or answered before merge)

Features and fixes

Dependencies: #11610 follow-redirects 1.16.2, #11560 re2js 2.9.1, #11609 minimatch 11 (mcp-server).

CI fix-forwards:

The range also carries everything else already on develop, such as the 10-31 issue-triage integration #11601.

Migrations (9, all additive)

  • core:
    • 1791000003500-EverConnectIdentity
    • 1791000003630-ConnectTimeOffBalancesToApproval
    • 1791000003660-AddOrganizationScreenshotCaptureAcknowledgement
    • 1791000003870-GrantOrganizationContactAddDeletePermissions
    • 1791000003880-NormalizeOrganizationContactCommentType
  • entitlement: 1791000003580-AddEntitlementLiveLineGrantUniqueIndex
  • integration-ever-works: 1791000003510-CreateEverWorksInboxPreference
  • subscription: 1791000003520-AddSubscriptionBillingChargeClaim, 1791000003540-AddSubscriptionReservedPlan

Restore point for gauzy_stage: CNPG pg-nightly-20261101020000 (completed, backupId 20261101T020001) plus WAL archiving (last archived 12:40Z, newer than the last failure), which allows point-in-time recovery.

Checks on develop

  • 7da5a66804: Static Checks, cspell and Release Demo are green.
  • cebf2b5a74: Docker Demo images built and booted on demo (SQLite), and /api/health returned 200.
  • Known reds, none from a merge that needs undoing:
    • GraphQL Schema: red since before today.
    • Egress audit every_trigger: rows 19 and 22 can't be exercised by the rc.8 mock yet (owner decision).
    • Egress audit browser modes: docs.gauzy.co link on the "What's new" settings page, red since the 06:34Z scheduled run.

Ever ID

🛑 Not a production release: stage → master waits for the owner.

🤖 Generated with Claude Code


Summary by cubic

Promotes develop to stage as a merge commit, carrying Ever Connect sign-in with Ever ID, subscription billing charge fencing, Ever Works inbox push, plus dependency bumps and CI fixes. Not a production release; stage → master waits for the owner.

Migrations (9, all additive)

  • Five in core, two in subscription, one each in entitlement and integration-ever-works.
  • A CNPG restore point plus WAL archiving is available for gauzy_stage.

Deployment notes

  • Ever ID sign-in is already on stage (auth-stage.ever.co); production stays off until k8s-gitops Admin Panel Bug #212–feat: style improvements on organizations page #214 merge.
  • Static Checks, cspell, and Release Demo are green on the promoted commit; Docker Demo images booted and /api/health returned 200.
  • Known reds, none from a merge needing undo: GraphQL Schema (pre-existing), egress-audit every_trigger rows not yet exercisable by the rc.8 mock, and an egress-audit browser-mode docs link.

Written for commit 7da5a66. Summary will update on new commits.

View guided diff Turn on auto-fix

evereq and others added 30 commits October 31, 2026 05:37
… a form

Two cases the Add task dialog's client filter makes easy to reach, since the
list now reloads whenever the client changes:

- An earlier project request that answered after a later one put the previous
  client's projects back. getProjects now drops a response once a newer
  request has started.
- Every reload re-applied the URL's ?projectId=, so in a form it replaced the
  project picked there (or the one on the task being edited) with the page's.
  A form's selector (skipGlobalChange) now takes the URL's project only while
  nothing is selected in it. The global selector follows the URL as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e disallowed

Where a route disallows past dates, minDate is today, but the menu still
listed Yesterday, Last Week, Last Month and now Last Year. The picker library
keeps such an entry in its list, and picking it gave a range starting today
and ending in the past. The presets now start on minDate at the earliest, and
the ones that end before its day are not offered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ogging-1769-4006

feat(core): opt-in DB_CREATE_IF_NOT_EXISTS and LOG_HTTP_REQUESTS
The template gate now also requires the web app to be served: App Platform
must send the web app's paths to the webapp component, and the Caddyfile
must keep a catch-all `handle { reverse_proxy webapp:... }` (a missing,
redirected or misdirected fallback is reported).

An env sample secret counts as empty only when nothing follows the `=`, or
empty quotes optionally followed by a comment: compose reads `KEY= # note`
as the value `# note`, which `${KEY:?}` accepts.

SECURITY.md names WSS for WebSocket connections, and the README says that
App Platform loses files stored in the API container on every redeploy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…for ShellCheck

The sed expression that strips dotenv's backtick quotes holds literal
backticks in single quotes, which ShellCheck reads as an unexpanded command
substitution (SC2016). Say so and disable that check for the one command.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s refunded

A line granted again after a revocation holds the revoked right next to
its live one, and the partial-refund path lowered both: it rewrote the
revoked row's quantity and appended a reduction event for it. The refund
handler now skips rights that are already revoked, so only the rights
still standing are lowered or withdrawn. Withdrawal replays are
unchanged.

The dual-ORM spec revokes and re-grants a line, delivers a partial
refund through the real consumer, and asserts that only the live right
is lowered, on TypeORM and MikroORM.

Refs #11023

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t spans it

Two separate one-day recurring holidays on 28 February and 1 March no longer
make 29 February a holiday in leap years; the leap day is added per holiday
range before it joins the shared set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cuments

When several documents carry the form's name, one with an http(s) link now
comes before a newer one whose link is not, so the dialog downloads the form
instead of reporting it unavailable. A form whose only link is not http(s) is
still found, so the dialog keeps saying it cannot be downloaded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…andidates and contacts

Contact details hold the inverse side of their one-to-one with an employee,
a candidate and an organization contact, so saving new details that name one
re-points that record to them. A caller creating without ORG_CONTACT_EDIT is
now refused (403) when the new details name any of the three.

Refs #5468

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The migration runs before the API starts. It now reads once per grant and
writes the missing rows and the rows to switch on in bounded multi-row
statements (at most 900 bind parameters each, as the permission reload does),
instead of one statement per role. The spec counts the statements for 600
editor roles.

Refs #5468

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f-eea-gate-9872

feat(organization): screen capture off for new organizations, EEA/UK acknowledgement to turn it on
…es open

The header's "Create lead / customer / client" quick actions and the
sidebar's "+" links open a contacts page's add form. They now show to those
who saw them before (ORG_CONTACT_EDIT or ALL_ORG_EDIT) and to holders of
ORG_CONTACT_ADD who can also open the contacts pages (ORG_CONTACT_VIEW), so a
create-only user is not sent to a page that turns them away. The rule lives
in one helper, mayOpenContactAddForm, in @gauzy/ui-core/core.

Refs #5468

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…k answers

The buttons waited for every plugin's config check together, so one slow
check held back the buttons whose checks had already answered. Each
check now starts hidden and shows its button on its own answer; the
order of the buttons is unchanged.

Refs #42

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- loadAvailableModules now ignores an answer once the selected project has
  changed, so modules requested for a project that a client cleared meanwhile
  are not offered, or saved, without a project.
- The new Client label is tied to the selector's input. ga-contact-selector
  gets an optional labelForId input, passed to ng-select's labelForId; left
  unset, nothing changes for its other users.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A form's selector re-applied ?projectId= on any reload that found it empty,
so a project the form had cleared (by hand, or because a client excluded it)
came back once the client was cleared again. The URL's project is now a
form selector's starting value only: its first list, while nothing is
selected. The global selector still follows the URL on every load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A locked picker widens every pick to one whole unit, but isCustomDate
compared that with the presets. Where future dates are disallowed the
current month preset ends today, so the whole month counted as custom and
Previous stepped back 31 days (31 Aug to 30 Sep from October) instead of
one month. The check moves to a pure isCustomDateRange helper that returns
false for locked pickers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d-ux-7643-7683-6715-7141

feat(desktop): screenshot popup close button, remembered mini timer position, custom and start/stop sounds
…approval-10183-5481

Both sides add one export to packages/ui-core/common/src/index.ts; both are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-10183-5481

feat(time-off): take approved leave from the balance and fix the request-form download
feat(plugin-auth-oidc): sign in with any OpenID Connect provider
…tage

Adds an opt-in Board view to a pipeline's Deals page, next to the table and the
cards grid (both stay as they are and remain the default). Each stage is a
column, in the stages' order; each card names the deal, its client, its
probability chip and who created it.

A user with EDIT_SALES_PIPELINES drags a card to another column to move the
deal to that stage: the card moves at once, shows a spinner while the deal is
saved through the existing PUT /deals/:id endpoint (stage and scope only, so a
stale title or probability is never written back), and goes back with the
error if the save fails. Users without the permission see the board read-only.

The view follows a `view=board` query parameter so it can be linked to and
survives a reload. The board reuses the tasks board's column and card styles
and the deals table's probability chip; the chip's level logic moves into a
shared helper used by both.

Refs #1660

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The template gate now works out where the Caddyfile sends each path the way
Caddy does: `handle` blocks are mutually exclusive and sorted by matcher
(a path matcher first, longest path first; then named matchers in order;
then the one without a matcher), and a `reverse_proxy` outside any `handle`
block runs only when none matched. Each API path must resolve to the API
and each web app path to the web app.

Before, a `handle /dashboard/* { reverse_proxy webapp:... }` passed as the
catch-all, and a `handle /graphql { reverse_proxy webapp:... }`, which
Caddy tries before `handle @api`, did not fail the /graphql check.

The README lists /swg-json and /swg-yaml with the other API paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… lock

The refund path skipped revoked rights by the status it had read, so a
revocation committing between that read and reduce() could still have
its quantity lowered and a reduction event appended. reduce() now checks
the status of the row it holds locked: a revoked right permits nothing,
so every reduction of it already holds, and it is answered as it stands
with no write and no event, as revoke() and a reduction to zero already
do. The consumer's own status check is dropped, so the rule lives in one
place.

Refs #11023

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dialog subscribed to project changes only after initializeForm and the
selected-project subscription had set the project, so neither loaded its
modules. They loaded only because the project selector then re-applied the
URL's project, which it no longer does over a form's own project. Editing a
task from its project's page would then have offered no modules, and saving
it unchanged would have dropped them. The project-change subscription now
comes first in ngOnInit, so the task's project and the page's selected
project load their modules themselves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…board

The project management dashboard gets a Recent activity panel, beside the
Inbox placeholder (kept): what was created, changed or deleted in the
organization, newest first, ten at a time with "Show more". Each row names the
record (linking tasks and projects to their pages), what was done, by whom,
the fields an update changed, and how long ago. It narrows to tasks or
projects, refreshes on demand, and has loading, empty and error states.

The rows come from the existing GET /activity-log through a new ui-core
ActivityLogService (page number as `skip`, organization always sent, absent
filters left out). What a user sees stays the API's decision: someone who may
not change the selected employee sees only their own activity.

Refs #4848

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#3912)

Settings > Roles & Permissions listed 368 toggles by label only; the grey line
under each label once repeated the label itself and was removed in #9877, so no
permission said what it lets a role do.

- i18n: ORGANIZATIONS_PAGE.PERMISSIONS.DESCRIPTIONS.<permission value> for every
  permission the page lists, in all 14 language files (ach carries English, as
  the rest of ach.json does). Added as the first child of PERMISSIONS: additions
  only, no existing line changes. The commerce ones follow the descriptions the
  plugins already declare in their permission contributions, worded for users.
- The page reads each label and description once per language through
  TranslateService.stream (not two pipes per row), shows the description as
  help text under the label (left out when a permission has none, so a raw key
  never shows), and the search now also matches the translated label and
  description; matching the code as words still works, so results only grow.
- permission-texts.ts: pure helpers (keys by permission value, absent-text
  handling, search matching), with specs; permission-i18n.spec.ts now fails CI
  when a listed permission has no description in a language, a description is
  keyed by something that is no permission value, or it repeats the label.
- Drops a leftover console.log from the search filter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…at is stored

The agent exit/logout restriction check on organization update took the
country after the update from a top-level `country` in the request,
which the organization does not store (it keeps its country on its
contact). It now judges the location the way the screen capture check
does: the stored region code, time zone and contact country, plus the
values the write stores (region code, time zone, the country of a
contact it carries or links by id).

- New organization-location.ts holds the shared location helpers
  (moved from screenshot-capture-acknowledgement.ts) and
  organizationLocations(), used by both checks and by the "moved into
  the EEA/UK" step that lifts employee restrictions.
- A contact the write links by id is read whenever it is not the current
  one, since the exit/logout rule depends on the location too.
- Specs: a request with only an unstored country does not change any
  decision; linked and carried contacts count; the stored location
  counts too.

Refs #9873

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nt-11023

fix(entitlement): race-safe grant and activation on a late order.placed
The edit dialog closes on an Escape keyup that reaches the document, so
pressing Escape to dismiss the banner hint also closed the dialog and threw
away unsaved edits. Escape is now handled on keyup: while the hint is open it
closes the hint and stops there; with the hint closed it reaches the dialog
as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…6569)

PUT /organization-team (and the GraphQL updateOrganizationTeam) rewrote every
member the edit did not name as a manager with no role, so a custom team role
given to a member was lost on each edit of the team. #6570 had fixed this in
2023; a later rewrite of updateOrganizationTeam brought it back.

teamRoleAfterEdit (team-manager-membership.ts) now decides the role of a member
already on the team: named as a manager -> the MANAGER role (unchanged); any
other member keeps the role they hold, unless it is the MANAGER role or another
of TEAM_MANAGER_ROLES (ADMIN, SUPER_ADMIN), which a manager left out loses as
before. Nobody keeps manager authority the edit took away, nothing new can be
granted (no DTO change), and a row is still written only when its role or (for
a caller who sets it) its manager flag changes.

Specs: the helper on its own, and the service edit keeping a custom role
without a write, clearing only the flag, promoting and demoting as before,
dropping an ADMIN/SUPER_ADMIN team role, and writing nothing for an unchanged
team.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
evereq and others added 17 commits November 1, 2026 18:18
#11567 moved ever-connect and ever-stats to the rc.8 contract and made rows
14, 19, 20 and 22; the egress audit still pinned rc.7, so the inputs job
failed ("The list of outbound calls is the pinned contract's").

- tools/egress-audit: @ever-co/connect-tools 1.0.0-rc.8 (lockfile
  regenerated with npm 11), eslint 10.14.0 and @typescript-eslint/parser
  8.72.1 (latest); typescript stays ~6.0.3 (the parser's peer range is
  <6.1.0, so 7.x is out).
- outbound-calls.config.json: the connection makes rows 14, 19, 20 and 22
  (each request verified in packages/plugins/ever-connect/src);
  outbound-calls.md regenerated (--write), every_trigger_exclude_rows
  drops them.
- patch-mock-clock.mjs: rc.8 keeps the mock's bucket line for line, so the
  patch now names rc.8 as a version it was written for.
- every_trigger adapter: fires row 14 (ever_id_login consented on the mock
  and accepted by the operator, with an https ZITADEL_CALLBACK_URL) and
  row 20 (a person's deletion request on the feed). Rows 19 and 22 need an
  Ever ID sign-in the rc.8 mock cannot serve (no issuer endpoints); the
  README documents the gap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g service and its spec

The Check Spelling job on develop (a43a16e, #11570) flags the identifiers bookkeptMetadata,
BOOKKEPT_* and isFinishable. File-level directives keep the exception local.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(subscription): cspell ignores bookkept / Finishable in the billing service and its spec
…swered copy, write-only 412, sending resumes

Findings of Greptile, Copilot and CodeRabbit on 20c49fa:

- A copy the member answered comes back out of an archive made in Gauzy: the
  move to `resolved` is kept (without a resolution, so the member's answer
  stays).
- A key with `inbox:write` but no `inbox:read` answers a 412 by sending once
  more on the version the 412 names (`details.current`), instead of a read it
  may not do.
- The preferences page says `missing_scope` when the connection's key may
  not file inbox items.
- INBOX_PUSH_SINCE moves whenever sending resumes (the mapping, its InboxItem
  setting or the inbox direction), not only on a direction change.
- The preview reads the paired people once, not per page.
- Inbox page: a link removed (another tab chosen) cancels its pending read,
  and a linked item is read once the list is served, so the list never lands
  over it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…box-push

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…14 cadence

- every_trigger: the row-14 wait now requires the sign-in client's GET (the
  identity worker's read) as well as the POST sent with the accept, so the
  disconnect cannot stop the worker before the read is audited (Copilot).
- outbound-calls: row 14's "How often" gives Gauzy's own schedule (a read
  5 s after the request, the wait doubling up to every 5 minutes) through
  gauzy_rows, as row 8 does (cubic).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sign-in client is asked for when ever_id_login is enabled; a request
that failed is sent again 30 s later, the wait doubling up to an hour
(EverIdLoginHandler.ensureRequested); the read runs on the worker's next
15 s pass at least 5 s later (CodeRabbit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…p on unarchive, backfill checkpoint, link guards

Findings of Greptile, Copilot and CodeRabbit on b7c9d3e:

- A copy the member answered, unarchived by Gauzy, keeps the member as the
  owner of its answer (a later Gauzy answer never goes over it).
- The inbox backfill checks the lease right after a page is read, and saves
  the run's checkpoint after each page, stopping when the run ended.
- The run plan names a missing inbox:write scope for an inbox that only
  sends; the inbox preview never counts this key's own filings as new items.
- Inbox page: a link that waited for the list never replaces an item opened
  meanwhile (success or failure of its read); a link waiting during "load
  more" opens with that page.
- i18n: "no other items".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hrough

A 422 refusal is stored as final (enabled() keeps it and ensureRequested()
skips a stored state); only no answer or another error is asked again by
the worker, 30 s later, the wait doubling up to an hour (cubic).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…only inbox, Angular conventions

Findings of cubic, Greptile and CodeRabbit on ab2f973:

- A send-only inbox mapping whose key lacks both inbox scopes is told that
  it lacks inbox:write, the scope it needs.
- The Ever Works inbox settings component keeps its template-only helpers
  protected and its ngOnInit to a named setup.
- The write-only 412 spec also shows a member's answer reaching Gauzy
  through the PATCH answer (its own event is then not needed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(egress-audit): move the harness to @ever-co/connect-tools 1.0.0-rc.8
CodeRabbit (outside-diff, on a1b9595): when the organization is no longer
mapped, the outbound queue refuses the row; the backfill now stops before it
instead of moving its cursor past it, so the row is not skipped when the run
resumes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…box-push

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rite-only 412, zoned SQLite times, last toggle

Findings of Greptile and Copilot on e1b08b3:

- A key without inbox:read never resends Gauzy's answer blind after a 412:
  the rest of the change goes first, and its PATCH answer tells whether the
  member answered; the answer follows on the next try or stays out.
- The Inbox feed marks SQLite's zone-less UTC datetimes as UTC, so the
  recovery sweep reads them the same in every process time zone.
- INBOX_PUSH_SINCE follows the last InboxItem toggle of a request, the one
  saved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat(ever-works): send the Gauzy Inbox's own items to Ever Works, per person and kind
…inted

The Check Spelling job on develop (9631807, #11543) flags these three words.
File-level directives keep the exceptions local.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(inbox,ever-works): cspell ignores datetimes / refetched / checkpointed
Copilot AI balanced review requested due to automatic review settings November 1, 2026 21:36
@coderabbitai

coderabbitai Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: cb4ffe7e-59d6-4d93-90ab-d7ef87b289c0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@socket-security

Copy link
Copy Markdown

@evereq

evereq commented Nov 1, 2026

Copy link
Copy Markdown
Member Author

AI-review summary for this cascade:

  • CodeRabbit: skipped (auto-reviews are off for non-default base branches). Every PR in this range was reviewed individually before it reached develop.
  • CodeQL: 7 alerts, each answered on its thread; none blocks the cascade.
    • redact-request-url: linear in practice (sticky regex, . and @ excluded from its classes).
    • Four trailing-slash trims: they run on operator configuration only.
    • ui-runtime-config: runs on the app's own index.html.
    • Two hits in spec files.
  • Follow-up (not blocking): a shared loop-based trimTrailingSlashes() helper to silence the four trim alerts.

Merge check: git merge-tree stage + develop is clean, and the result's tree equals develop's.

@greptile-apps

greptile-apps Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Critical impact] The release reaches identity, billing, time-off balances, and several shared product workflows.

Fix automatically approved leave skipping its balance check and deduction before merging.

Findings

  1. P1 Approved leave skips balance deductions ▶

Summary

Promotes identity, billing, Inbox sync, leave-balance, desktop, and web changes to stage.

  • Gauzy Inbox items can reach paired people in Ever Works.
  • Time-off decisions can record balance changes in the same transaction.

Acknowledgments supplied by evereq: the existing GraphQL check failure, egress rows 19 and 22 unsupported by the mock, and the known documentation-link browser check failure are not reported as new defects.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[File leave request] --> B{Policy needs approval?}
  B -->|Yes| C[Requested]
  C --> D[Approval transaction]
  D --> E[Check and deduct balance]
  E --> F[Approved]
  B -->|No| G[Save as approved]
  G --> H[Balance check and deduction skipped]
Loading

Reviews (1) · Last reviewed commit: "Merge pull request #11623 from ever-co/f..." · Reviewed by Greptile

Comment on lines +88 to +89
// Keeps the leave balance an approval took following the request's edits and removal (#10183).
readonly timeOffBalanceDeductionService?: TimeOffBalanceDeductionService

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Approved leave skips balance deductions

When a policy has requiresApproval=false, create() saves the request directly as APPROVED without calling the new deduction service. A later approval does not repair this because balanceEffectOf(APPROVED, APPROVED) returns null.

Employees keep their full balance, and requireSufficientBalance does not stop requests beyond the available days. Save automatically approved requests and their deductions in the same transaction, and add coverage for this path.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Three critical issues remain: production admin password resets are enabled, stale account settings can permit screenshots, and Cloudinary deletion can target the wrong tenant or leave files behind.

3 open issues
What changed in this PR

Promotes develop to stage for manual testing. This is not a production release.

Changes:

  • Adds Ever ID integration, billing charge fencing, and Ever Works inbox synchronization.
  • Carries UI, desktop, permissions, reporting, and data-management changes.
  • Updates dependencies, migrations, deployment configuration, and CI tooling.

This pull request requires changes.

  • Critical — 1 vote: Production deployment workflow enables admin password resets. Preserve the existing disabled policy or make it operator-controlled.
  • Critical — 1 vote: Agent API can apply stale screenshot settings after an account switch. Discard responses that no longer match the current account and employee.
  • Critical — 3 votes: File-storage provider can delete against the wrong Cloudinary account or report success while a file remains. Configure the tenant’s client and verify the deletion result.
File Description
tsconfig.json Adds the OIDC plugin path.
tools/​ever-platform/​fixtures/​import-bad/​packages/​plugins/​ever-connect/​src/​connect-imports-zitadel-file.ts Adds an identity import-boundary fixture.
tools/​egress-audit/​ui-routes.json Adds the What's New route.
tools/​egress-audit/​patch-mock-clock.mjs Supports the rc.8 mock clock.
tools/​egress-audit/​package.json Updates audit dependencies.
tools/​egress-audit/​egress-audit.config.json Updates audited contract rows.
packages/​ui-core/​shared/​src/​lib/​timesheet/​gauzy-filters/​gauzy-filters.component.html Adds a filter-action slot.
packages/​ui-core/​shared/​src/​lib/​time-off/​settings-mutation/​time-off-settings-mutation.component.html Adds the balance requirement setting.
packages/​ui-core/​shared/​src/​lib/​tasks/​task-status-select/​task-status-select.module.ts Updates selector imports.
packages/​ui-core/​shared/​src/​lib/​tasks/​task-select/​task/​task.component.html Adds input and label bindings.
packages/​ui-core/​shared/​src/​lib/​tasks/​add-task-dialog/​add-task-dialog.utils.ts Checks project/client compatibility.
packages/​ui-core/​shared/​src/​lib/​tasks/​add-task-dialog/​add-task-dialog.module.ts Imports dialog dependencies.
packages/​ui-core/​shared/​src/​lib/​selectors/​date-range-picker/​date-range-picker.component.html Disables unavailable previous ranges.
packages/​ui-core/​shared/​src/​lib/​selectors/​date-range-picker/​date-picker.interface.ts Adds year presets.
packages/​ui-core/​shared/​src/​lib/​report/​index.ts Exports report helpers.
packages/​ui-core/​shared/​src/​lib/​report/​export/​index.ts Exports report-export APIs.
packages/​ui-core/​shared/​src/​lib/​record-view/​record-view.component.ts Recognizes API placeholders.
packages/​ui-core/​shared/​src/​lib/​project/​project-mutation/​project-mutation.component.ts Uses first-party placeholders.
packages/​ui-core/​shared/​src/​lib/​organizations/​index.ts Exports the acknowledgement dialog.
packages/​ui-core/​shared/​src/​lib/​favorite-toggle/​favorite-toggle.component.ts Adds an appearance input.
packages/​ui-core/​shared/​src/​lib/​favorite-toggle/​favorite-toggle.component.html Binds button appearance.
packages/​ui-core/​shared/​src/​lib/​expenses/​expenses-mutation/​expenses-mutation.component.scss Styles the receipt indicator.
packages/​ui-core/​shared/​src/​lib/​expenses/​expenses-mutation/​expenses-mutation.component.html Shows the receipt indicator.
packages/​ui-core/​shared/​src/​lib/​expenses/​expenses-mutation/​attach-receipt/​attach-receipt.component.ts Filters legacy sample receipts.
packages/​ui-core/​shared/​src/​lib/​expenses/​expenses-mutation/​attach-receipt/​attach-receipt.component.scss Styles the empty receipt state.
packages/​ui-core/​shared/​src/​lib/​expenses/​expenses-mutation/​attach-receipt/​attach-receipt.component.html Shows an empty receipt hint.
packages/​ui-core/​shared/​src/​lib/​dialogs/​dialogs.module.ts Imports drag-and-drop support.
packages/​ui-core/​shared/​src/​lib/​contact-selector/​contact-selector.component.html Associates the selector label.
packages/​ui-core/​shared/​src/​lib/​components/​email-verification-notice/​email-verification-notice.component.ts Removes an unused import.
packages/​ui-core/​shared/​src/​lib/​components/​changelog-entry/​changelog-entry.component.html Displays entry dates in UTC.
packages/​ui-core/​core/​src/​lib/​utils/​index.ts Exports permission and acknowledgement helpers.
packages/​ui-core/​core/​src/​lib/​services/​quick-actions/​index.ts Exports quick-action services.
packages/​ui-core/​core/​src/​lib/​services/​index.ts Exports new service groups.
packages/​ui-core/​core/​src/​lib/​services/​deals/​deals.service.ts Adds deal-stage updates.
packages/​ui-core/​core/​src/​lib/​services/​auth/​index.ts Exports registration configuration.
packages/​ui-core/​core/​src/​lib/​services/​activity-log/​index.ts Exports the activity service.
packages/​ui-core/​core/​src/​lib/​directives/​index.ts Exports the registration directive.
packages/​ui-core/​core/​src/​lib/​auth/​registration-enabled.guard.ts Guards public registration.
packages/​ui-core/​core/​src/​lib/​auth/​index.ts Exports the registration guard.
packages/​ui-core/​common/​src/​lib/​utils/​placeholder-image.ts Builds first-party placeholder URLs.
packages/​ui-core/​common/​src/​lib/​constants/​app.constants.ts Replaces the external placeholder.
packages/​ui-core/​common/​src/​index.ts Exports shared utilities.
packages/​ui-config/​src/​lib/​environments/​model.ts Adds OIDC UI configuration.
packages/​ui-auth/​src/​lib/​components/​social-links/​social-links.component.html Supports parameterized provider labels.
packages/​ui-auth/​src/​lib/​components/​login/​login.component.html Hides registration when disabled.
packages/​ui-auth/​src/​lib/​components/​login-workspace/​login-workspace.component.html Hides registration when disabled.
packages/​ui-auth/​src/​lib/​components/​login-magic/​login-magic.component.html Hides registration when disabled.
packages/​ui-auth/​src/​lib/​components/​forgot-password/​forgot-password.component.html Hides registration when disabled.
packages/​ui-auth/​src/​lib/​auth.routes.ts Guards the registration route.
packages/​ui-auth/​src/​lib/​auth.module.ts Imports the registration directive.
packages/​plugins/​subscription/​src/​lib/​subscription/​subscription.entity.ts Adds reserved-plan tracking.
packages/​plugins/​subscription/​src/​lib/​subscription-streamed-events.ts Adds settlement event types.
packages/​plugins/​subscription/​src/​lib/​subscription-streamed-events.spec.ts Tests the event catalogue.
packages/​plugins/​subscription/​src/​lib/​subscription-item/​subscription-item.service.spec.ts Updates catalogue test fixtures.
packages/​plugins/​registry/​src/​lib/​application/​plugin-tenant/​queries/​handlers/​get-plugin-tenant-users.handler.ts Replaces legacy avatar URLs.
packages/​plugins/​registry/​src/​lib/​application/​plugin-subscription/​commands/​upgrade-plugin-subscription.command.ts Adds plugin scoping.
packages/​plugins/​registry/​src/​lib/​application/​plugin-subscription/​commands/​downgrade-plugin-subscription.command.ts Adds plugin scoping.
packages/​plugins/​public-layout-ui/​src/​lib/​public-layout.routes.ts Guards workspace creation.
packages/​plugins/​public-layout-ui/​jest.config.ts Adds Angular test defaults.
packages/​plugins/​order/​src/​index.ts Exports the order-state reader.
packages/​plugins/​job-proposal-ui/​src/​lib/​proposal/​components/​proposal-details/​proposal-details.component.ts Narrows template-member visibility.
packages/​plugins/​integration-zapier/​src/​lib/​zapier.types.ts Adds settings and public configuration types.
packages/​plugins/​integration-zapier/​src/​lib/​zapier.service.settings.spec.ts Updates settings expectations.
packages/​plugins/​integration-zapier/​src/​lib/​zapier.config.ts Defines the webhook URL limit.
packages/​plugins/​integration-zapier/​src/​lib/​dto/​index.ts Exports the settings DTO.
packages/​plugins/​integration-github-ui/​src/​index.ts Exports project-sync UI.
packages/​plugins/​integration-ever-works/​src/​lib/​sync/​ever-works-sync.context.ts Tracks the originating inbox recipient.
packages/​plugins/​integration-ever-works/​src/​lib/​sync/​entities/​ever-works-sync.entities.ts Adds the Gauzy inbox link type.
packages/​plugins/​integration-ever-works/​src/​lib/​mapping/​dto/​ever-works-mapping.dto.ts Adds inbox backfill control.
packages/​plugins/​integration-ever-works-ui/​src/​lib/​components/​preview/​ever-works-preview.component.ts Indicates truncated previews.
packages/​plugins/​integration-activepieces/​src/​lib/​dto/​index.ts Exports the MCP create DTO.
packages/​plugins/​inbox/​src/​lib/​inbox-item.mapper.ts Extracts inbox item mapping.
packages/​plugins/​inbox/​src/​index.ts Exports the inbox feed.
packages/​plugins/​inbox-ui/​src/​i18n/​en.json Adds an item-link error message.
packages/​plugins/​ever-stats/​package.json Updates Connect dependencies.
packages/​plugins/​ever-connect/​src/​lib/​readme-table.spec.ts Updates outbound contract rows.
packages/​plugins/​ever-connect/​src/​lib/​ever-connect-store.db.spec.ts Separates identity migration tables.
packages/​plugins/​ever-connect/​src/​lib/​ever-connect-lease.ts Adds the shared connection lease.
packages/​plugins/​ever-connect/​src/​lib/​ever-connect-config.provider.ts Provides identity configuration.
packages/​plugins/​ever-connect/​src/​lib/​ever-connect-audit.service.ts Adds identity audit fields.
packages/​plugins/​ever-connect/​src/​lib/​entities/​ever-connect-connection.entity.ts Adds URL-check state.
packages/​plugins/​ever-connect/​src/​index.ts Exports the person-data port.
packages/​plugins/​ever-connect/​project.json Adds the identity plugin dependency.
packages/​plugins/​entitlement/​src/​lib/​events/​index.ts Exports settlement handling.
packages/​plugins/​entitlement/​src/​lib/​events/​entitlement-order-line-policy.adapter.spec.ts Updates the grant fixture.
packages/​plugins/​entitlement/​src/​lib/​events/​entitlement-grant.consumer.spec.ts Updates grant lookup tests.
packages/​plugins/​entitlement/​src/​lib/​entitlement/​entitlement.service.grant-references.spec.ts Updates the service fixture.
packages/​plugins/​entitlement/​src/​lib/​database/​migrations/​index.ts Registers the grant index migration.
packages/​plugins/​docs-ui/​src/​lib/​pages/​settings/​docs-settings-page.component.ts Removes an unused import.
packages/​plugins/​docs-ui/​src/​lib/​dialogs/​category-dialog.component.ts Removes an unused import.
packages/​plugins/​docs-ui/​src/​lib/​dialogs/​bulk-categories-dialog.component.ts Migrates template control flow.
packages/​plugins/​docs-ui/​src/​lib/​components/​table/​cells/​updated-cell.component.ts Migrates template control flow.
packages/​plugins/​docs-ui/​src/​lib/​components/​table/​cells/​source-badge.component.ts Migrates template control flow.
packages/​plugins/​docs-ui/​src/​lib/​components/​table/​cells/​name-cell-thumbnail.spec.ts Updates template expectations.
packages/​plugins/​docs-ui/​src/​lib/​components/​links/​document-attach-dialog.component.ts Removes an unused import.
packages/​plugins/​docs-ui/​src/​lib/​components/​filter-bar/​facet-multiselect.component.ts Migrates template control flow.
packages/​plugins/​docs-ui/​src/​lib/​components/​cards/​docs-cards-thumbnail.spec.ts Updates template expectations.
packages/​plugins/​docs-ui/​src/​i18n/​en.json Adds document-panel labels.
packages/​plugins/​auth-zitadel/​src/​lib/​services/​zitadel-signin.service.ts Resolves identity hints and emits sign-in events.
packages/​plugins/​auth-zitadel/​src/​lib/​events/​zitadel-account.events.ts Adds the sign-in event.
packages/​plugins/​auth-zitadel/​src/​index.ts Exports identity ports.
packages/​plugins/​auth-oidc/​tsconfig.spec.json Configures OIDC tests.
packages/​plugins/​auth-oidc/​tsconfig.lib.json Configures the OIDC library.
packages/​plugins/​auth-oidc/​tsconfig.json Configures the OIDC project.
packages/​plugins/​auth-oidc/​src/​lib/​auth-oidc.tokens.ts Defines the settings token.
packages/​plugins/​auth-oidc/​src/​index.ts Exports the OIDC plugin.
packages/​plugins/​auth-oidc/​jest.config.ts Configures OIDC test execution.
packages/​plugins/​auth-oidc/​eslint.config.cjs Configures OIDC linting.
packages/​mcp-server/​package.json Updates minimatch.
packages/​desktop-window/​src/​index.ts Exports window-position helpers.
packages/​desktop-ui-lib/​src/​lib/​time-tracker/​web-portal/​index.ts Exports web-portal helpers.
packages/​desktop-ui-lib/​src/​lib/​time-tracker/​time-tracker.component.scss Styles footer separators.
packages/​desktop-ui-lib/​src/​lib/​time-tracker/​sounds/​index.ts Exports timer sounds.
packages/​desktop-ui-lib/​src/​lib/​time-tracker/​selection-prefill/​index.ts Exports selection-prefill helpers.
packages/​desktop-ui-lib/​src/​lib/​time-tracker/​organization-selector/​organization-switch.service.spec.ts Tests timer-start state.
packages/​desktop-ui-lib/​src/​lib/​time-tracker/​connectivity/​index.ts Exports connectivity notices.
packages/​desktop-ui-lib/​src/​lib/​shared/​features/​project-selector/​+state/​project-selector.service.ts Drops stale project responses.
packages/​desktop-ui-lib/​src/​lib/​shared/​features/​client-selector/​+state/​client-selector.service.ts Drops stale client responses.
packages/​desktop-ui-lib/​src/​lib/​setup/​setup.component.html Adds server-host selection.
packages/​desktop-ui-lib/​src/​lib/​settings/​settings.component.scss Styles screenshot-sound settings.
packages/​desktop-ui-lib/​src/​lib/​settings/​server-host/​index.ts Exports server-host helpers.
packages/​desktop-ui-lib/​src/​lib/​settings/​screenshot-sound/​index.ts Exports screenshot-sound settings.
packages/​desktop-ui-lib/​src/​lib/​screen-capture/​screen-capture.component.scss Styles the notification close button.
packages/​desktop-ui-lib/​src/​lib/​screen-capture/​screen-capture.component.html Adds a notification close button.
packages/​desktop-lib/​src/​lib/​sound-settings/​sound-settings.ts Reads timer-sound settings.
packages/​desktop-lib/​src/​lib/​sound-settings/​sound-settings.ipc.ts Exposes sound settings over IPC.
packages/​desktop-lib/​src/​lib/​sound-settings/​index.ts Exports sound settings.
packages/​desktop-lib/​src/​lib/​screenshot-sound/​screenshot-sound.ipc.ts Adds screenshot-sound IPC.
packages/​desktop-lib/​src/​lib/​screenshot-sound/​index.ts Exports screenshot-sound support.
packages/​desktop-lib/​src/​lib/​offline/​utils/​index.ts Exports update helpers.
packages/​desktop-lib/​src/​lib/​offline/​transactions/​user-transaction.ts Skips empty updates.
packages/​desktop-lib/​src/​lib/​offline/​transactions/​timer-transaction.ts Skips empty updates.
packages/​desktop-lib/​src/​lib/​offline/​transactions/​task-transaction.ts Skips empty updates.
packages/​desktop-lib/​src/​lib/​offline/​transactions/​project-transaction.ts Skips empty updates.
packages/​desktop-lib/​src/​lib/​offline/​transactions/​interval-transaction.ts Skips empty updates.
packages/​desktop-lib/​src/​lib/​offline/​desktop-offline-mode-handler.ts Uses shared connectivity timing.
packages/​desktop-lib/​src/​lib/​offline/​dao/​tag.dao.ts Skips empty updates.
packages/​desktop-lib/​src/​lib/​offline/​dao/​client.dao.ts Skips empty updates.
packages/​desktop-lib/​src/​lib/​offline/​connectivity-timing.ts Defines connectivity timing.
packages/​desktop-lib/​src/​lib/​network/​index.ts Exports network helpers.
packages/​desktop-lib/​src/​lib/​network/​desktop-network-ipc.ts Exposes local addresses over IPC.
packages/​desktop-lib/​src/​lib/​interfaces/​i-read-write-file.ts Clarifies read failures.
packages/​desktop-lib/​src/​lib/​config/​read-write-file.ts Reflects optional read results.
packages/​desktop-lib/​src/​lib/​config/​index.ts Exports UI runtime configuration.
packages/​desktop-lib/​src/​index.ts Exports desktop features.
packages/​desktop-core/​src/​lib/​store/​concretes/​application-setting-store.service.ts Adds sound defaults.
packages/​core/​src/​lib/​time-tracking/​time-log/​time-log.resolver.ts Returns weekly spend.
packages/​core/​src/​lib/​time-tracking/​time-log/​schema/​time-log.type.gql Adds weekly spend fields.
packages/​core/​src/​lib/​time-tracking/​time-log/​schema/​time-log.api.gql Documents weekly spend.
packages/​core/​src/​lib/​time-off-request/​time-off-request.module.ts Connects leave balances.
packages/​core/​src/​lib/​time-off-policy/​time-off-policy.service.ts Persists balance requirements.
packages/​core/​src/​lib/​time-off-policy/​time-off-policy.resolver.ts Adds the policy input.
packages/​core/​src/​lib/​time-off-policy/​time-off-policy.entity.ts Adds the balance requirement.
packages/​core/​src/​lib/​time-off-policy/​schema/​time-off-policy.type.gql Exposes the policy setting.
packages/​core/​src/​lib/​time-off-balance/​repository/​mikro-orm-time-off-balance-deduction.repository.ts Adds the deduction repository.
packages/​core/​src/​lib/​tenant/​tenant.subscriber.ts Replaces external placeholders.
packages/​core/​src/​lib/​tenant/​tenant.controller.ts Documents registration refusal.
packages/​core/​src/​lib/​tenant/​commands/​tenant-feature-organization.create.command.ts Adds missing-only creation.
packages/​core/​src/​lib/​tenant/​commands/​handlers/​tenant-feature-organization.create.handler.ts Passes creation options.
packages/​core/​src/​lib/​role/​commands/​tenant-role-bulk-create.command.ts Adds missing-only role creation.
packages/​core/​src/​lib/​role-permission/​default-role-permissions.ts Adds contact permissions.
packages/​core/​src/​lib/​request-approval/​request-approval.module.ts Connects leave balances.
packages/​core/​src/​lib/​request-approval/​commands/​handlers/​request-approval.status.handler.ts Documents balance settlement.
packages/​core/​src/​lib/​placeholder-image/​placeholder-image.module.ts Registers the placeholder controller.
packages/​core/​src/​lib/​placeholder-image/​index.ts Exports placeholder support.
packages/​core/​src/​lib/​organization/​organization.bulk.spec.ts Updates the organization fixture.
packages/​core/​src/​lib/​organization/​dto/​organization-setting.dto.ts Adds capture settings.
packages/​core/​src/​lib/​organization/​dto/​index.ts Exports acknowledgement DTOs.
packages/​core/​src/​lib/​organization/​default-organizations.ts Adds a public tagline.
packages/​core/​src/​lib/​organization-team/​organization-team.service.ts Excludes assigned comments from team saves.
packages/​core/​src/​lib/​organization-team/​organization-team.entity.ts Makes comment assignments read-only.
packages/​core/​src/​lib/​organization-contact/​organization-contact.permissions.ts Defines create-only contact behavior.
packages/​core/​src/​lib/​organization-contact/​organization-contact.module.ts Registers the contact comment policy.
packages/​core/​src/​lib/​organization-contact/​commands/​organization-contact-create.command.ts Adds create-only options.
packages/​core/​src/​lib/​logger/​index.ts Exports logging helpers.
packages/​core/​src/​lib/​logger/​http-request-logger/​index.ts Exports request logging.
packages/​core/​src/​lib/​invite/​schema/​invite.type.gql Documents capture defaults for invitations.
packages/​core/​src/​lib/​export-import/​skip-export.decorator.ts Documents core export exclusions.
packages/​core/​src/​lib/​expense/​expense.resolver.ts Clarifies expense scoping.
packages/​core/​src/​lib/​employee/​employee.entity.ts Makes comment assignments read-only.
packages/​core/​src/​lib/​employee-statistics/​employee-statistics.controller.membership.spec.ts Updates permission fixtures.
packages/​core/​src/​lib/​database/​provision/​index.ts Exports database provisioners.
packages/​core/​src/​lib/​core/​util/​organization-sensitive-relations.config.ts Protects acknowledgement-user data.
packages/​core/​src/​lib/​core/​file-storage/​providers/​wasabi-s3.provider.ts Adds strict deletion.
packages/​core/​src/​lib/​core/​file-storage/​providers/​provider.ts Adds the strict-deletion contract.
packages/​core/​src/​lib/​core/​file-storage/​providers/​digitalocean-s3.provider.ts Adds strict deletion.
packages/​core/​src/​lib/​core/​errors/​api-error-codes.ts Adds the capture acknowledgement error.
packages/​core/​src/​lib/​core/​entities/​internal.ts Exports leave deductions.
packages/​core/​src/​lib/​core/​entities/​index.ts Registers leave deductions.
packages/​core/​src/​lib/​comment/​parent-access/​record-type-spelling.ts Compares record-type spellings.
packages/​core/​src/​lib/​comment/​parent-access/​index.ts Exports comment access support.
packages/​core/​src/​lib/​comment/​parent-access/​comment-parent-access-policy.decorator.ts Defines policy metadata.
packages/​core/​src/​lib/​comment/​comment.service.owner-scope.spec.ts Updates access fixtures.
packages/​core/​src/​lib/​comment/​comment.service.mentions.spec.ts Updates access fixtures.
packages/​core/​src/​lib/​comment/​comment.service.http-status.spec.ts Updates access fixtures.
packages/​core/​src/​lib/​comment/​comment.service.author.spec.ts Updates access fixtures.
packages/​core/​src/​lib/​comment/​comment.controller.ts Uses policy-aware reads.
packages/​core/​src/​lib/​bootstrap/​index.ts Adds opt-in database provisioning.
packages/​core/​src/​lib/​bootstrap/​bootstrap.module.ts Registers request logging.
packages/​core/​src/​lib/​auth/​auth-switches/​index.ts Exports authentication switches.
packages/​contracts/​src/​lib/​role-permission.model.ts Adds contact permissions.
packages/​contracts/​src/​lib/​report.model.ts Adds weekly spend fields.
packages/​contracts/​src/​lib/​auth.model.ts Defines registration configuration.
packages/​contracts/​src/​index.ts Exports shared helpers.
packages/​config/​src/​lib/​environments/​ienvironment.ts Adds authentication switches.
packages/​config/​src/​lib/​environments/​environment.ts Resolves authentication switches.
packages/​config/​src/​lib/​environments/​environment.prod.ts Resolves production switches.
packages/​config/​src/​index.ts Exports switch helpers.
packages/​auth/​src/​lib/​public-api.spec.ts Updates OIDC public API expectations.
packages/​auth/​src/​lib/​oidc/​oidc.module.ts Registers email sign-in.
packages/​auth/​src/​lib/​oidc/​index.ts Exports email sign-in.
packages/​auth/​src/​lib/​facebook/​facebook.strategy.ts Uses shared email verification handling.
jest.preset.js Updates an OIDC test comment.
docker-compose.demo.yml Adds local email-code logging.
apps/​server/​src/​index.ts Registers network-address IPC.
apps/​server-api/​src/​index.ts Registers network-address IPC.
apps/​gauzy/​src/​app/​pages/​teams/​teams-mutation/​teams-mutation.component.ts Uses first-party placeholders.
apps/​gauzy/​src/​app/​pages/​tasks/​tasks.module.ts Imports shared task views.
apps/​gauzy/​src/​app/​pages/​tasks/​components/​task/​task.component.ts Opens duplication as a new task.
apps/​gauzy/​src/​app/​pages/​tasks/​components/​task-view/​task-view-header.component.scss Styles linked project names.
apps/​gauzy/​src/​app/​pages/​settings/​roles-permissions/​permission-sections.ts Lists contact permissions.
apps/​gauzy/​src/​app/​pages/​reports/​weekly-time-reports/​weekly-time-reports/​weekly-time-reports.component.ts Detects available spend.
apps/​gauzy/​src/​app/​pages/​reports/​weekly-time-reports/​weekly-time-reports/​weekly-time-reports.component.html Displays weekly spend.
apps/​gauzy/​src/​app/​pages/​reports/​time-reports/​time-reports.module.ts Adds export-button dependencies.
apps/​gauzy/​src/​app/​pages/​projects/​projects.module.ts Uses shared comments.
apps/​gauzy/​src/​app/​pages/​projects/​components/​project-view/​project-board/​board-minimap.component.html Adds board minimap rendering.
apps/​gauzy/​src/​app/​pages/​projects/​components/​project-create/​create.component.html Adds deferred document attachments.
apps/​gauzy/​src/​app/​pages/​pipelines/​table-components/​pipeline-deal-probability/​pipeline-deal-probability.component.ts Shares deal probability badge logic.
apps/​gauzy/​src/​app/​pages/​pipelines/​pipelines.module.ts Imports the deals board.
apps/​gauzy/​src/​app/​pages/​pipelines/​pipeline-deals/​pipeline-deals.component.scss Styles the board toggle.
apps/​gauzy/​src/​app/​pages/​organizations/​edit-organization/​edit-organization-routing.module.ts Loads permitted location data.
apps/​gauzy/​src/​app/​pages/​employees/​edit-employee/​edit-employee-profile/​edit-employee-documents/​edit-employee-documents.component.html Migrates template control flow.
apps/​gauzy/​src/​app/​pages/​employees/​activity/​time-activities/​time-activities/​time-activities.component.html Adds CSV export.
apps/​gauzy/​src/​app/​pages/​employees/​activity/​time-activities/​time-activities.module.ts Imports export-button dependencies.
apps/​gauzy/​src/​app/​pages/​dashboard/​project-management/​project-management-details/​project-management-details.component.html Adds recent activity.
apps/​gauzy/​src/​app/​pages/​dashboard/​dashboard.module.ts Imports recent activity.
apps/​gauzy/​src/​app/​pages/​contacts/​contacts.component.ts Adds action-permission configuration.
apps/​gauzy/​src/​app/​pages/​contacts/​contact-view/​contact-view.module.ts Imports shared notes.
apps/​gauzy/​src/​app/​pages/​contacts/​contact-mutation/​contact-mutation.component.ts Filters linkable projects.
apps/​gauzy-e2e/​tests/​bdd/​steps/​roles-permissions.steps.ts Updates permission fixtures.
apps/​api/​package.json Adds the OIDC plugin dependency.
apps/​agent/​src/​main/​window-manager.ts Handles notification closure.
apps/​agent/​src/​main/​screenshot-interval.ts Adds organization capture settings.
apps/​agent/​src/​main/​init/​ipcMain.ts Registers screenshot-sound handlers.
apps/​agent/​src/​main/​events/​tray-notify.ts Reflects capture permissions.
apps/​agent/​src/​main/​api.ts Loads employee organization settings.
.scripts/​env.ts Adds OIDC environment configuration.
.scripts/​configure.ts Generates OIDC UI configuration.
.gitignore Excludes Caddy secrets.
.github/​workflows/​egress-audit.yml Enables the baseline rewalk.
.github/​workflows/​deploy-do-app-platform-prod.yml Changes the admin password-reset setting.
.github/​ISSUE_TEMPLATE/​config.yml Adds private vulnerability reporting.
.env.docker Documents authentication switches.
.dockerignore Excludes Caddy secrets.
.deploy/​webapp/​replacements.sed Adds OIDC runtime substitution.

Review effort: Balanced

DEMO: 'false'
NODE_ENV: 'production'
ADMIN_PASSWORD_RESET: 'false'
ADMIN_PASSWORD_RESET: 'true'
const path = `/api/employee/${employeeId}`;
const employee: Partial<TEmployeeResponse> = await this.get(path, {});
// With its organisation: the agent captures the screen only when the organisation allows it too (issue #9872)
const employee: Partial<TEmployeeResponse> = await this.get(path, { 'relations[0]': 'organization' });
Comment on lines +63 to +64
async deleteFileOrFail(filePath: string): Promise<void> {
await this.deleteFile(filePath);

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

42 issues found across 1079 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/gauzy/src/app/pages/settings/roles-permissions/roles-permissions.component.scss">

<violation number="1" location="apps/gauzy/src/app/pages/settings/roles-permissions/roles-permissions.component.scss:266">
P2: The 11px description text resolves to #7E7E8F on the Gauzy light background, roughly 3.8–4.0:1 contrast, which fails WCAG AA for small text. Measure the resolved color on the light card before accepting it, and pick a darker token or a larger size if the description must stay legible.</violation>
</file>

<file name="packages/core/src/lib/core/context/request-context.middleware.ts">

<violation number="1" location="packages/core/src/lib/core/context/request-context.middleware.ts:108">
P2: The start line logs route-parameter values that the completion line redacts. Without `req.params`, a short or UUID-shaped `:token` or `:code` segment (for example `/api/public/invoice/:id/:token`) is written in clear at the start of the request. Consider dropping the URL path from the start line, or logging the redacted URL only on the completion line where `req.params` is known.</violation>
</file>

<file name="apps/gauzy/src/app/pages/projects/components/project-view/project-activity/project-activity.component.scss">

<violation number="1" location="apps/gauzy/src/app/pages/projects/components/project-view/project-activity/project-activity.component.scss:112">
P3: The `.feed-status-pill` is `nowrap` with no width cap, so a long status name overflows `.feed-status` and can overlap the time column. Add `max-width: 100%` and `overflow: hidden` so the pill stays inside its row.</violation>
</file>

<file name="apps/gauzy/src/app/pages/projects/components/project-view/project-board/board-minimap.component.ts">

<violation number="1" location="apps/gauzy/src/app/pages/projects/components/project-view/project-board/board-minimap.component.ts:58">
P3: Cancel the pending animation-frame measurement when the minimap is destroyed or before scheduling another one. Otherwise a board teardown can invoke `markForCheck()` after this component has been destroyed, and rapid column updates queue redundant measurements.</violation>

<violation number="2" location="apps/gauzy/src/app/pages/projects/components/project-view/project-board/board-minimap.component.ts:67">
P3: `onPointerDown` starts a drag for any mouse button. A right-click on the minimap scrolls the board and captures the pointer. Return early unless the primary button is pressed.</violation>
</file>

<file name="packages/core/src/lib/expense/expense.resolver.ts">

<violation number="1" location="packages/core/src/lib/expense/expense.resolver.ts:354">
P3: This doc clause omits that `onlyMe: true` returns no expenses with no employee record, whatever the role. The role exception applies only to the non-`onlyMe` path. Add that exception here so the comment matches `resolveEmployeeIds`.</violation>
</file>

<file name="packages/core/src/lib/logger/http-request-logger/http-request-logger.options.ts">

<violation number="1" location="packages/core/src/lib/logger/http-request-logger/http-request-logger.options.ts:8">
P3: The `enabled` doc comment says logging is off unless `LOG_HTTP_REQUESTS` is `true`, but `parseToBoolean` also enables it for `1`. Update the comment to say `true` or `1` so it matches the behavior.</violation>
</file>

<file name="packages/core/src/lib/deal/deal.resolver.ts">

<violation number="1" location="packages/core/src/lib/deal/deal.resolver.ts:94">
P3: The reads state `VIEW_SALES_PIPELINES` on each field, so "inherit" is inaccurate here. Say "state" to match the sentence it follows.</violation>
</file>

<file name="packages/core/src/lib/database/provision/database-identifier.ts">

<violation number="1" location="packages/core/src/lib/database/provision/database-identifier.ts:27">
P3: `assertValidDatabaseName` lets through a MySQL name ending in a space, which MySQL refuses. The failure then surfaces at the `create` stage with a generic server error instead of the `config` message naming `DB_NAME`. Add the trailing-space refusal here for the MySQL limit.</violation>
</file>

<file name=".github/workflows/deploy-do-app-platform-prod.yml">

<violation number="1" location=".github/workflows/deploy-do-app-platform-prod.yml:58">
P1: This flips production `ADMIN_PASSWORD_RESET` back to `'true'`, which re-enables the e-mailed password reset for Admin and Super Admin accounts. That reverses the #7821 hardening that this workflow had set to `'false'`. The PR description only covers the stage promotion and never mentions this prod change. Keep `'false'` unless the switch is being turned on on purpose, and call that out in the PR.</violation>
</file>

<file name="packages/core/src/lib/invite/schema/invite.type.gql">

<violation number="1" location="packages/core/src/lib/invite/schema/invite.type.gql:413">
P2: This paragraph says every other `contactOrganization` member is passed through, but the handler drops the owned columns first (`id`, `tenantId`, `contactId`, `image`, audit user ids, and more, also inside `contact`) via `sanitizeContactOrganization`. Clients reading this schema description would expect those members to reach the create. Name the stripped set and note the sanitizer.</violation>
</file>

<file name="apps/gauzy/src/app/pages/pipelines/pipeline-deals/pipeline-deals-board/pipeline-deals-board.component.html">

<violation number="1" location="apps/gauzy/src/app/pages/pipelines/pipeline-deals/pipeline-deals-board/pipeline-deals-board.component.html:42">
P2: A card that is still saving stays clickable. Opening it can load the deal's pre-move stage, and saving that form may revert the move. Disable the link while `card.saving` is set.</violation>
</file>

<file name="apps/gauzy/src/app/pages/projects/components/project-create/create.component.html">

<violation number="1" location="apps/gauzy/src/app/pages/projects/components/project-create/create.component.html:21">
P3: The Documents aside always reserves its 22rem grid column, even when the panel renders nothing. Users without `DOCS_READ`, `FEATURE_DOCUMENTS`, or the upload permissions will see the project form narrowed next to an empty column. Gate the `<aside>` on the panel's visibility, or hide the column when the panel is not shown.</violation>
</file>

<file name="apps/gauzy/src/app/pages/invoices/invoice-payments/payments.component.ts">

<violation number="1" location="apps/gauzy/src/app/pages/invoices/invoice-payments/payments.component.ts:150">
P2: The status write compares float sums with `===`, so two-payment splits on cent amounts can be marked OVERPAID instead of FULLY_PAID. For example, payments of 50.1 and 50.2 on a 100.3 invoice sum to 100.30000000000001. Round both values to cents before passing them to `updateInvoiceStatus`.</violation>
</file>

<file name="apps/gauzy/src/app/pages/pipelines/pipeline-deals/pipeline-deals-board/pipeline-deals-board.utils.ts">

<violation number="1" location="apps/gauzy/src/app/pages/pipelines/pipeline-deals/pipeline-deals-board/pipeline-deals-board.utils.ts:30">
P3: This comment says the name fallback matches the deals table, but the table only shows `createdByUser.name`. Reword it to say the card falls back to first and last name, then email, which the table does not do.</violation>
</file>

<file name="apps/gauzy/src/app/pages/settings/changelog/changelog-entry-dialog/changelog-entry-dialog.component.html">

<violation number="1" location="apps/gauzy/src/app/pages/settings/changelog/changelog-entry-dialog/changelog-entry-dialog.component.html:27">
P2: Error messages are not linked to their inputs. Add `[attr.aria-invalid]` on each input and an `id` on each `<small class="error">` referenced by `aria-describedby`, so screen readers announce the error when the field is focused.</violation>

<violation number="2" location="apps/gauzy/src/app/pages/settings/changelog/changelog-entry-dialog/changelog-entry-dialog.component.html:127">
P3: The image link error text says only http:// or https:// addresses are allowed, but `imageUrlValidator` also accepts bundled `assets/...` image paths. Use a dedicated message for this field that lists both forms.</violation>
</file>

<file name="packages/core/src/lib/logger/http-request-logger/http-request-logger.module.ts">

<violation number="1" location="packages/core/src/lib/logger/http-request-logger/http-request-logger.module.ts:19">
P2: Importing `HttpRequestLoggerModule` without `forRoot()` fails at startup: the constructor injects `HTTP_REQUEST_LOGGER_OPTIONS`, which only `forRoot()` provides. Either give the static `@Module` default options and middleware providers, or document `forRoot()` as the only supported entry point.</violation>
</file>

<file name="packages/core/src/lib/account-deletion/account-deletion-files.ts">

<violation number="1" location="packages/core/src/lib/account-deletion/account-deletion-files.ts:464">
P2: The non-ASCII branch loads every `invite` and `email_sent` row of the workspace into memory to filter them in JavaScript, inside the account-deletion transaction. `email_sent` grows with every email a workspace sends, so this is costly for large tenants. Narrow the SELECT in SQL first, for example by filtering on the ASCII domain or local-part, then do the exact match in code.</violation>
</file>

<file name="packages/config/src/lib/database-helpers.ts">

<violation number="1" location="packages/config/src/lib/database-helpers.ts:200">
P2: `decodeCaCertificate` returns PEM text unchanged, so a PEM stored with literal `\n` sequences instead of real line breaks is passed to TLS as an invalid CA. Normalize the escaped line breaks in the PEM branch. A PEM body never contains a backslash, so the replacement is safe.</violation>
</file>

<file name="packages/core/src/lib/comment/comment.resolver.ts">

<violation number="1" location="packages/core/src/lib/comment/comment.resolver.ts:242">
P2: `createComment` validates `entity` but not `actorType`, which the REST route rejects through `@IsEnum(ActorTypeEnum)`. An unknown `actorType` on GraphQL is silently stored as `System` instead of refused. Add the same check here, or state why the GraphQL path intentionally accepts it.</violation>
</file>

<file name="packages/auth/src/lib/social-auth-emails.ts">

<violation number="1" location="packages/auth/src/lib/social-auth-emails.ts:8">
P3: `flagProviderConfirmedEmails` can return `value: undefined`, but `SocialAuthEmail.value` promises a string. Make the field `string | undefined` or omit invalid entries so the type matches the runtime result.</violation>

<violation number="2" location="packages/auth/src/lib/social-auth-emails.ts:53">
P3: This claim rule now lives in two places. `OidcEmailSignInService.userinfoEmail` in `oidc/oidc-email-sign-in.service.ts` re-implements `email` plus `email_verified === true`, with blank handling that differs from this helper. Consider reusing `emailsFromOidcClaims` there so the verified rule and blank check live in one place.</violation>
</file>

<file name="packages/core/src/lib/employee/employee.entity.ts">

<violation number="1" location="packages/core/src/lib/employee/employee.entity.ts:852">
P2: This `persistence: false` only takes effect under TypeORM. The MikroORM mapping drops it silently, so the comment's claim that saving an employee never links comments does not hold under `DB_ORM=mikro-orm` from this flag alone. Either add a MikroORM-side guard or narrow the comment to say the protection comes from `withoutAssignedComments`, and cover the MikroORM mapping in a test.</violation>
</file>

<file name="apps/gauzy/src/app/pages/organizations/organization-route-relations.ts">

<violation number="1" location="apps/gauzy/src/app/pages/organizations/organization-route-relations.ts:36">
P2: `holds(permission)` runs eagerly in `permitted.map`, outside the `catchError`, so a synchronous throw skips the fallback and the settings page fails to open. Wrap the call in `defer` so every failure becomes a stream error that `catchError` handles, and add `defer` to the rxjs import.</violation>
</file>

<file name="apps/gauzy/src/app/pages/projects/components/project-view/project-board/board-filter.ts">

<violation number="1" location="apps/gauzy/src/app/pages/projects/components/project-view/project-board/board-filter.ts:70">
P2: The white initials fail contrast for many avatar colours. At `34%` lightness, 85 of 360 hues (about 51–182) fall below WCAG AA 4.5:1, down to 3.8:1 at hue 60, on 9px text. Lower the lightness to 30%, which keeps every hue at 4.75:1 or higher, and fix the comment to match.</violation>

<violation number="2" location="apps/gauzy/src/app/pages/projects/components/project-view/project-board/board-filter.ts:88">
P3: The `#` is stripped after trimming, so `# 12` keeps a leading space and will not match key `GAU-12`. Strip the `#` first, then trim.</violation>
</file>

<file name="apps/gauzy/src/app/pages/projects/components/project-view/project-view-page.component.html">

<violation number="1" location="apps/gauzy/src/app/pages/projects/components/project-view/project-view-page.component.html:66">
P2: The Documents count badge only appears after the Documents tab has been opened, and it resets on every project load. Comments gets its count before the tab opens, but Documents has no equivalent read, so the tab shows no count on first view. Consider prefetching the document-link count in `load()`, the way `loadCommentCount()` does.</violation>
</file>

<file name="packages/contracts/src/lib/time-off.model.ts">

<violation number="1" location="packages/contracts/src/lib/time-off.model.ts:238">
P3: This contract says deduction days are always positive, but the service deliberately persists zero-day records and the entity allows zero. Document the field as non-negative and mention retained zero-day charges.</violation>
</file>

<file name="apps/gauzy/src/app/pages/pipelines/pipeline-deals/pipeline-deals.component.html">

<violation number="1" location="apps/gauzy/src/app/pages/pipelines/pipeline-deals/pipeline-deals.component.html:57">
P2: Deals at stages added after this page loaded disappear from the board because the host replaces each API-provided `deal.stage` relation with a lookup in the stale pipeline snapshot before passing `deals` here. Preserve the deal's returned stage relation when the snapshot lookup is missing, so the board can create the fallback column.</violation>
</file>

<file name="packages/core/src/lib/auth/auth-switches/registration-policy.service.ts">

<violation number="1" location="packages/core/src/lib/auth/auth-switches/registration-policy.service.ts:90">
P2: The first-tenant exception is not safe across multiple MikroORM API instances: each process can observe an empty database and pass this check before creating a tenant. Use a database-level lock or an atomic/rechecked first-tenant creation transaction for MikroORM deployments.</violation>
</file>

<file name="apps/api/config/source-map-rebase.js">

<violation number="1" location="apps/api/config/source-map-rebase.js:65">
P2: A relative `sourceRoot` is cleared even for URL or absolute `sources` entries, so those entries no longer resolve to the same source after rebasing. Preserve the sourceRoot semantics for every entry, or leave maps with mixed relative-root/non-relative sources unchanged.</violation>
</file>

<file name="packages/core/src/lib/deal/deal.controller.ts">

<violation number="1" location="packages/core/src/lib/deal/deal.controller.ts:137">
P3: The delete route advertises 204 while `@HttpCode` returns 202 and the handler returns a `DeleteResult`. Document `HttpStatus.ACCEPTED` or change the actual response to match 204.</violation>
</file>

<file name=".deploy/caddy/Caddyfile">

<violation number="1" location=".deploy/caddy/Caddyfile:18">
P2: The API matcher omits the exact `/public` path, so that request falls through to the web app instead of the API. Add `/public` alongside `/public/*`.</violation>
</file>

<file name=".github/workflows/egress-audit.yml">

<violation number="1" location=".github/workflows/egress-audit.yml:137">
P2: `BASELINE_REWALK=true` discards every nonzero result from `check-baseline-shrink`, not only the expected growth result. A schema or other validation error can then pass because `check-baseline-rewalk.mjs` checks only `base_commit` and added route/link pairs; capture the exit code and fail for statuses other than the documented growth status before running the rewalk check.</violation>
</file>

<file name=".devcontainer/codespaces-env.sh">

<violation number="1" location=".devcontainer/codespaces-env.sh:56">
P2: The Codespace setup forwards `CLIENT_BASE_URL` but leaves the tracked `APP_LINK` and email URLs at localhost. Because `.env.local` overrides these values, Ever Works links are dropped and generated email links can still target the viewer’s localhost; preserve or rewrite these URL settings for the forwarded UI too.</violation>
</file>

<file name="apps/agent/src/main/util.ts">

<violation number="1" location="apps/agent/src/main/util.ts:176">
P1: `updateAgentSetting` ignores an explicit `organization: null`, leaving a previously true `organizationAllowsScreenshotCapture` value in local storage. Clear this value for null while preserving the existing value only when the relation is omitted.</violation>
</file>

<file name="apps/gauzy/src/app/pages/projects/components/project-create/create.component.ts">

<violation number="1" location="apps/gauzy/src/app/pages/projects/components/project-create/create.component.ts:74">
P2: The attachment retry path requires project-edit permission even though this create page is available with `ORG_PROJECT_ADD` alone. A create-only user cannot retry failed attachments because `edit` rejects before `attachPending`; retry attachments without forcing an update for users lacking edit permission, or gate this recovery path appropriately.</violation>
</file>

<file name="packages/core/src/lib/bootstrap/index.ts">

<violation number="1" location="packages/core/src/lib/bootstrap/index.ts:656">
P2: This call enables provisioning for MySQL URL-based configurations, but the MySQL provisioner drops URL-only driver settings before opening its admin connection. Pass the URL through to the MySQL driver or reject unsupported URL-only settings instead of checking a potentially different server.</violation>

<violation number="2" location="packages/core/src/lib/bootstrap/index.ts:656">
P2: The provisioning target must follow the active ORM configuration; this line always uses TypeORM options even when `DB_ORM=mikro-orm`. Select and normalize the active ORM's options, or require the two configurations to agree before provisioning.</violation>
</file>

<file name="packages/core/src/lib/core/file-storage/providers/provider.ts">

<violation number="1" location="packages/core/src/lib/core/file-storage/providers/provider.ts:64">
P1: Override `deleteFileOrFail` for Cloudinary to configure the current tenant's client and reject a `not found` result; otherwise account deletion can report success while leaving the asset behind.</violation>
</file>

<file name="apps/agent/src/main/api.ts">

<violation number="1" location="apps/agent/src/main/api.ts:345">
P1: Discard this response when the signed-in account or employee has changed before it completes; otherwise a delayed response can restore account A's screenshot permission while account B's organization disables capture.</violation>
</file>

Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.

View guided diff | Turn on auto-fix | Re-trigger cubic

DEMO: 'false'
NODE_ENV: 'production'
ADMIN_PASSWORD_RESET: 'false'
ADMIN_PASSWORD_RESET: 'true'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This flips production ADMIN_PASSWORD_RESET back to 'true', which re-enables the e-mailed password reset for Admin and Super Admin accounts. That reverses the #7821 hardening that this workflow had set to 'false'. The PR description only covers the stage promotion and never mentions this prod change. Keep 'false' unless the switch is being turned on on purpose, and call that out in the PR.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At .github/workflows/deploy-do-app-platform-prod.yml, line 58:

<comment>This flips production `ADMIN_PASSWORD_RESET` back to `'true'`, which re-enables the e-mailed password reset for Admin and Super Admin accounts. That reverses the #7821 hardening that this workflow had set to `'false'`. The PR description only covers the stage promotion and never mentions this prod change. Keep `'false'` unless the switch is being turned on on purpose, and call that out in the PR.</comment>

<file context>
@@ -55,7 +55,7 @@ jobs:
           DEMO: 'false'
           NODE_ENV: 'production'
-          ADMIN_PASSWORD_RESET: 'false'
+          ADMIN_PASSWORD_RESET: 'true'
           API_BASE_URL: 'https://apida.gauzy.co'
           CLIENT_BASE_URL: 'https://app.gauzy.co'
</file context>
Suggested change
ADMIN_PASSWORD_RESET: 'true'
ADMIN_PASSWORD_RESET: 'false'

Comment on lines +176 to +177
...(employee.organization && {
organizationAllowsScreenshotCapture: employee.organization.allowScreenshotCapture === true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: updateAgentSetting ignores an explicit organization: null, leaving a previously true organizationAllowsScreenshotCapture value in local storage. Clear this value for null while preserving the existing value only when the relation is omitted.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/agent/src/main/util.ts, line 176:

<comment>`updateAgentSetting` ignores an explicit `organization: null`, leaving a previously true `organizationAllowsScreenshotCapture` value in local storage. Clear this value for null while preserving the existing value only when the relation is omitted.</comment>

<file context>
@@ -164,11 +172,43 @@ export function updateAgentSetting(employee: Partial<TEmployeeResponse>) {
 		kbMouseTracking: employee.trackKeyboardMouseActivity,
 		allowScreenshotCapture: employee.allowScreenshotCapture ?? false,
+		// Read with the employee; a response without it keeps the value read last
+		...(employee.organization && {
+			organizationAllowsScreenshotCapture: employee.organization.allowScreenshotCapture === true
+		}),
</file context>
Suggested change
...(employee.organization && {
organizationAllowsScreenshotCapture: employee.organization.allowScreenshotCapture === true
+\t\t...(employee.organization !== undefined && {
+\t\t\torganizationAllowsScreenshotCapture: employee.organization?.allowScreenshotCapture === true

* @throws Error when the provider did not delete the file.
*/
async deleteFileOrFail(filePath: string): Promise<void> {
await this.deleteFile(filePath);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Override deleteFileOrFail for Cloudinary to configure the current tenant's client and reject a not found result; otherwise account deletion can report success while leaving the asset behind.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/core/src/lib/core/file-storage/providers/provider.ts, line 64:

<comment>Override `deleteFileOrFail` for Cloudinary to configure the current tenant's client and reject a `not found` result; otherwise account deletion can report success while leaving the asset behind.</comment>

<file context>
@@ -49,6 +49,21 @@ export abstract class Provider<T> {
+	 * @throws Error when the provider did not delete the file.
+	 */
+	async deleteFileOrFail(filePath: string): Promise<void> {
+		await this.deleteFile(filePath);
+	}
+
</file context>

const path = `/api/employee/${employeeId}`;
const employee: Partial<TEmployeeResponse> = await this.get(path, {});
// With its organisation: the agent captures the screen only when the organisation allows it too (issue #9872)
const employee: Partial<TEmployeeResponse> = await this.get(path, { 'relations[0]': 'organization' });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Discard this response when the signed-in account or employee has changed before it completes; otherwise a delayed response can restore account A's screenshot permission while account B's organization disables capture.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/agent/src/main/api.ts, line 345:

<comment>Discard this response when the signed-in account or employee has changed before it completes; otherwise a delayed response can restore account A's screenshot permission while account B's organization disables capture.</comment>

<file context>
@@ -341,7 +341,8 @@ export class ApiService {
 		const path = `/api/employee/${employeeId}`;
-		const employee: Partial<TEmployeeResponse> = await this.get(path, {});
+		// With its organisation: the agent captures the screen only when the organisation allows it too (issue #9872)
+		const employee: Partial<TEmployeeResponse> = await this.get(path, { 'relations[0]': 'organization' });
 		if (employee?.id) {
 			authConfig.user.employee = employee;
</file context>

line-height: 1rem;
text-align: start;
// Material light and dark do not define gauzy-text-color-2; fall back to their hint color.
color: var(--gauzy-text-color-2, var(--text-hint-color));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The 11px description text resolves to #7E7E8F on the Gauzy light background, roughly 3.8–4.0:1 contrast, which fails WCAG AA for small text. Measure the resolved color on the light card before accepting it, and pick a darker token or a larger size if the description must stay legible.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/gauzy/src/app/pages/settings/roles-permissions/roles-permissions.component.scss, line 266:

<comment>The 11px description text resolves to #7E7E8F on the Gauzy light background, roughly 3.8–4.0:1 contrast, which fails WCAG AA for small text. Measure the resolved color on the light card before accepting it, and pick a darker token or a larger size if the description must stay legible.</comment>

<file context>
@@ -250,12 +250,21 @@ $muted: var(--text-hint-color);
+    line-height: 1rem;
+    text-align: start;
+    // Material light and dark do not define gauzy-text-color-2; fall back to their hint color.
+    color: var(--gauzy-text-color-2, var(--text-hint-color));
+  }
 
</file context>

* filter in use. The search takes a card's title or its key, with or without the `#` the task's header shows it with.
*/
export function matchesBoardFilter(card: IBoardFilterCard, filter: IBoardFilter): boolean {
const search = filter.search.trim().replace(/^#/, '').toLowerCase();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The # is stripped after trimming, so # 12 keeps a leading space and will not match key GAU-12. Strip the # first, then trim.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/gauzy/src/app/pages/projects/components/project-view/project-board/board-filter.ts, line 88:

<comment>The `#` is stripped after trimming, so `# 12` keeps a leading space and will not match key `GAU-12`. Strip the `#` first, then trim.</comment>

<file context>
@@ -0,0 +1,124 @@
+ * filter in use. The search takes a card's title or its key, with or without the `#` the task's header shows it with.
+ */
+export function matchesBoardFilter(card: IBoardFilterCard, filter: IBoardFilter): boolean {
+	const search = filter.search.trim().replace(/^#/, '').toLowerCase();
+	if (search && ![card.title, card.key].some((text) => text?.toLowerCase().includes(search))) return false;
+	if (filter.people.length) {
</file context>
Suggested change
const search = filter.search.trim().replace(/^#/, '').toLowerCase();
const search = filter.search.replace(/^\\s*#/, '').trim().toLowerCase();

if (changes['columnCount']) {
this.segments = Array.from({ length: this.columnCount }, (_, index) => index);
// The new columns are on the page once this pass ends.
requestAnimationFrame(this._measure);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Cancel the pending animation-frame measurement when the minimap is destroyed or before scheduling another one. Otherwise a board teardown can invoke markForCheck() after this component has been destroyed, and rapid column updates queue redundant measurements.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/gauzy/src/app/pages/projects/components/project-view/project-board/board-minimap.component.ts, line 58:

<comment>Cancel the pending animation-frame measurement when the minimap is destroyed or before scheduling another one. Otherwise a board teardown can invoke `markForCheck()` after this component has been destroyed, and rapid column updates queue redundant measurements.</comment>

<file context>
@@ -0,0 +1,120 @@
+		if (changes['columnCount']) {
+			this.segments = Array.from({ length: this.columnCount }, (_, index) => index);
+			// The new columns are on the page once this pass ends.
+			requestAnimationFrame(this._measure);
+		}
+	}
</file context>

timeOffRequestId: ID;
balance?: ITimeOffBalance;
balanceId: ID;
/** Working days taken from the balance. Always positive. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This contract says deduction days are always positive, but the service deliberately persists zero-day records and the entity allows zero. Document the field as non-negative and mention retained zero-day charges.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/contracts/src/lib/time-off.model.ts, line 238:

<comment>This contract says deduction days are always positive, but the service deliberately persists zero-day records and the entity allows zero. Document the field as non-negative and mention retained zero-day charges.</comment>

<file context>
@@ -199,6 +224,21 @@ export interface ITimeOffBalance extends IBasePerTenantAndOrganizationEntityMode
+	timeOffRequestId: ID;
+	balance?: ITimeOffBalance;
+	balanceId: ID;
+	/** Working days taken from the balance. Always positive. */
+	days: number;
+}
</file context>
Suggested change
/** Working days taken from the balance. Always positive. */
/** Working days taken from the balance. Non-negative; an edit can retain a zero-day record. */

* @returns The result of the deletion.
*/
@ApiOperation({ summary: 'Delete a deal' })
@ApiResponse({ status: HttpStatus.NO_CONTENT, description: 'The deal has been successfully deleted.' })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The delete route advertises 204 while @HttpCode returns 202 and the handler returns a DeleteResult. Document HttpStatus.ACCEPTED or change the actual response to match 204.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/core/src/lib/deal/deal.controller.ts, line 137:

<comment>The delete route advertises 204 while `@HttpCode` returns 202 and the handler returns a `DeleteResult`. Document `HttpStatus.ACCEPTED` or change the actual response to match 204.</comment>

<file context>
@@ -81,4 +97,85 @@ export class DealController extends CrudController<Deal> {
+	 * @returns The result of the deletion.
+	 */
+	@ApiOperation({ summary: 'Delete a deal' })
+	@ApiResponse({ status: HttpStatus.NO_CONTENT, description: 'The deal has been successfully deleted.' })
+	@ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Deal not found' })
+	@HttpCode(HttpStatus.ACCEPTED)
</file context>
Suggested change
@ApiResponse({ status: HttpStatus.NO_CONTENT, description: 'The deal has been successfully deleted.' })
@ApiResponse({ status: HttpStatus.ACCEPTED, description: 'The deal has been successfully deleted.' })

* `verified`, so a strategy sets the flag from the provider's own guarantee and never assumes it.
*/
export interface SocialAuthEmail {
value: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: flagProviderConfirmedEmails can return value: undefined, but SocialAuthEmail.value promises a string. Make the field string | undefined or omit invalid entries so the type matches the runtime result.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/auth/src/lib/social-auth-emails.ts, line 8:

<comment>`flagProviderConfirmedEmails` can return `value: undefined`, but `SocialAuthEmail.value` promises a string. Make the field `string | undefined` or omit invalid entries so the type matches the runtime result.</comment>

<file context>
@@ -0,0 +1,54 @@
+ * `verified`, so a strategy sets the flag from the provider's own guarantee and never assumes it.
+ */
+export interface SocialAuthEmail {
+	value: string;
+	verified: boolean;
+}
</file context>

@evereq

evereq commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

Verified on demo (develop 7da5a66804, SQLite) before merging:

Merging to stage as a merge commit.

@evereq
evereq merged commit ee004e7 into stage Nov 2, 2026
68 of 81 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants