Skip to content

fix(backend): fix upsert on non multiple refs (#17511) - #17518

Merged
Jeremy Cloarec (JeremyCloarec) merged 2 commits into
masterfrom
issue/17511
Aug 13, 2026
Merged

fix(backend): fix upsert on non multiple refs (#17511)#17518
Jeremy Cloarec (JeremyCloarec) merged 2 commits into
masterfrom
issue/17511

Conversation

@JeremyCloarec

@JeremyCloarec Jeremy Cloarec (JeremyCloarec) commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

This pull request enhances the upsert utilities and their test coverage, specifically focusing on the handling of reference fields in upsert operations. The main change is the export and thorough testing of the generateRefsInputsForUpsert function, ensuring correct behavior for both single and multiple reference fields under various scenarios, including synchronization mode and confidence-based updates.

Upsert Utility Improvements

  • Exported the generateRefsInputsForUpsert function from upsert-utils.js for direct use in other modules and tests.
  • Fixed the logic for determining when a reference field should be updated, ensuring that updates only occur when there is actual input data and the update is allowed by the current confidence and protection rules.

Test Coverage Enhancements

  • Added comprehensive unit tests for generateRefsInputsForUpsert in middleware-test.js, covering:
    • Non-multiple (single) reference fields (e.g., createdBy): tests for not overwriting with null/undefined, proper filling, replacement with higher confidence, protection against flickering, and explicit removal in synchronization mode.
    • Multiple reference fields (e.g., objectLabel): tests for adding missing values, avoiding unnecessary updates, and full replacement in synchronization mode.
    • Ensuring ignored refs not present in the update patch.
  • Updated test imports to include the now-exported generateRefsInputsForUpsert.

Related issues

How to test this PR

Checklist

  • I consider the submitted work as finished
  • I tested the code for its functionality
  • I wrote test cases for the relevant use cases (coverage and e2e)
  • I added/updated the relevant documentation (either on GitHub or on Notion)
  • Where necessary, I refactored code to improve the overall quality

Further comments

Copilot AI lite review requested due to automatic review settings August 5, 2026 08:46

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.

Pull request overview

This PR fixes confidence-based upsert behavior for single-reference fields (e.g., createdBy) to prevent “data cleaning” (clearing an existing ref when the incoming ref is empty), and it exports generateRefsInputsForUpsert to enable direct unit testing.

Changes:

  • Exported generateRefsInputsForUpsert from upsert-utils.js.
  • Tightened single-ref upsert conditions so updates only occur when the input actually contains data (unless in full synchronization mode).
  • Added unit tests covering single vs multiple ref upsert scenarios, including sync mode and confidence/protection cases.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
opencti-platform/opencti-graphql/src/utils/upsert-utils.js Exports generateRefsInputsForUpsert and fixes the single-ref “updatable” condition to avoid null/empty overwrites outside sync mode.
opencti-platform/opencti-graphql/tests/01-unit/database/middleware-test.js Adds unit tests for generateRefsInputsForUpsert across single/multiple refs and sync mode behaviors.
Suppressed comments (6)

opencti-platform/opencti-graphql/tests/01-unit/database/middleware-test.js:433

  • Same as above: to reflect actual resolved store shape, resolvedElement['created-by'] should be the author internal_id string, not the full object.
        const resolvedElement = { ...baseIndicator, 'created-by': authorA };

opencti-platform/opencti-graphql/tests/01-unit/database/middleware-test.js:454

  • Same as above: resolvedElement['created-by'] should be a stored internal_id string.
        const resolvedElement = { ...baseIndicator, 'created-by': authorA };

opencti-platform/opencti-graphql/tests/01-unit/database/middleware-test.js:464

  • Same as above: resolvedElement['created-by'] should be a stored internal_id string.
        const resolvedElement = { ...baseIndicator, 'created-by': authorA };

opencti-platform/opencti-graphql/tests/01-unit/database/middleware-test.js:474

  • Same as above: resolvedElement['created-by'] should be a stored internal_id string.
        const resolvedElement = { ...baseIndicator, 'created-by': authorA };

opencti-platform/opencti-graphql/tests/01-unit/database/middleware-test.js:485

  • Same as above: resolvedElement['created-by'] should be a stored internal_id string.
        const resolvedElement = { ...baseIndicator, 'created-by': authorA };

opencti-platform/opencti-graphql/tests/01-unit/database/middleware-test.js:545

  • Same as above: even in this test, resolvedElement['created-by'] should reflect the stored internal_id string.
      const resolvedElement = { ...baseIndicator, 'created-by': authorA };

// To prevent too much flickering on multi sources the created-by will be replaced only for strict upper confidence
const isProtectedCreatedBy = relDef.databaseName === RELATION_CREATED_BY && !isCurrentEmptyData && !isConfidenceUpper;
const updatable = ((isInputWithData && isCurrentEmptyData) || isConfidenceMatch) && !isProtectedCreatedBy;
const updatable = isInputWithData && (isCurrentEmptyData || isConfidenceMatch) && !isProtectedCreatedBy;
describe('non multiple ref (createdBy)', () => {
it('should NOT replace an existing ref value with a null input (regression: no data cleaning)', () => {
// resolvedElement has an author, the incoming patch explicitly provides createdBy = null
const resolvedElement = { ...baseIndicator, 'created-by': authorA };
@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 34.07%. Comparing base (6ce2211) to head (942cb17).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #17518      +/-   ##
==========================================
- Coverage   34.08%   34.07%   -0.02%     
==========================================
  Files        3376     3376              
  Lines      137588   137588              
  Branches    37228    37228              
==========================================
- Hits        46891    46877      -14     
- Misses      90697    90711      +14     
Flag Coverage Δ
opencti-client-python 48.37% <ø> (ø)
opencti-front 10.98% <ø> (ø)
opencti-graphql 69.11% <100.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aHenryJard A. Jard (aHenryJard) added the filigran team Item from the Filigran team. label Aug 5, 2026
@JeremyCloarec
Jeremy Cloarec (JeremyCloarec) merged commit c61b936 into master Aug 13, 2026
60 of 61 checks passed
@JeremyCloarec
Jeremy Cloarec (JeremyCloarec) deleted the issue/17511 branch August 13, 2026 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

filigran team Item from the Filigran team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(backend): Upsert clears existing createdBy to null when incoming confidence is higher (createdBy ref path lacks emptiness guard)

4 participants