Skip to content

Commit e98682d

Browse files
committed
[backend] Upsert: skip decay computation if no score change (#15476)
1 parent c622aab commit e98682d

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

opencti-platform/opencti-graphql/src/utils/upsert-utils.js

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,25 +128,46 @@ export const buildUpdatePatchForUpsert = (user, resolvedElement, type, basePatch
128128
if (type === ENTITY_TYPE_INDICATOR) {
129129
if (resolvedElement.decay_applied_rule) {
130130
// Do not compute decay again when:
131-
// - base score does not change
132-
// - same userIs has already updated to the same score previously
131+
// - base score does not change (indicator is still at its initial score, decay not started yet)
133132
const isScoreInUpsertSameAsBaseScore = updatePatch.decay_base_score === resolvedElement.decay_base_score && updatePatch.decay_base_score === resolvedElement.x_opencti_score;
133+
// - same userId has already updated to the same score previously
134134
const hasSameScoreChangedBySameSource = hasSameSourceAlreadyUpdateThisScore(user.id, updatePatch.x_opencti_score, resolvedElement.decay_history);
135-
if (isScoreInUpsertSameAsBaseScore || hasSameScoreChangedBySameSource) {
136-
logApp.debug(`[OPENCTI][DECAY] on upsert indicator skip decay, do not change score, keep:${resolvedElement.x_opencti_score}`, { elementScore: resolvedElement.x_opencti_score, patchScore: updatePatch.x_opencti_score, isScoreInUpsertSameAsBaseScore, hasSameScoreChangedBySameSource });
135+
// - the live score in the upsert is identical to the current live score (e.g. a Playbook re-ingesting
136+
// the indicator bundle without any score change — the bundle carries the current decayed score,
137+
// not the original base score, so addIndicator incorrectly computes a new decay start from it)
138+
const isLiveScoreUnchanged = updatePatch.x_opencti_score === resolvedElement.x_opencti_score;
139+
if (isScoreInUpsertSameAsBaseScore || hasSameScoreChangedBySameSource || isLiveScoreUnchanged) {
140+
logApp.debug(
141+
`[OPENCTI][DECAY] on upsert indicator skip decay, do not change score, keep:${resolvedElement.x_opencti_score}`,
142+
{
143+
elementScore: resolvedElement.x_opencti_score,
144+
patchScore: updatePatch.x_opencti_score,
145+
isScoreInUpsertSameAsBaseScore,
146+
hasSameScoreChangedBySameSource,
147+
isLiveScoreUnchanged,
148+
},
149+
);
137150
// don't reset score, valid_from & valid_until
138151
updatePatch.x_opencti_score = resolvedElement.x_opencti_score; // don't change the score
139152
updatePatch.valid_from = resolvedElement.valid_from;
140153
updatePatch.valid_until = resolvedElement.valid_until;
141154
// don't reset decay attributes
142155
updatePatch.revoked = resolvedElement.revoked;
156+
updatePatch.decay_base_score = resolvedElement.decay_base_score; // preserve the original base score
143157
updatePatch.decay_base_score_date = resolvedElement.decay_base_score_date;
144158
updatePatch.decay_applied_rule = resolvedElement.decay_applied_rule;
145159
updatePatch.decay_history = []; // History is multiple, forcing to empty array will prevent any modification
146160
updatePatch.decay_next_reaction_date = resolvedElement.decay_next_reaction_date;
147161
} else {
148-
// As base_score as change, decay will be reset by upsert
149-
logApp.debug('[OPENCTI][DECAY] Decay is restarted', { elementScore: resolvedElement.x_opencti_score, initialPatchScore: basePatch.x_opencti_score, updatePatchScore: updatePatch.x_opencti_score });
162+
// As base_score has changed, decay will be reset by upsert
163+
logApp.debug(
164+
'[OPENCTI][DECAY] Decay is restarted',
165+
{
166+
elementScore: resolvedElement.x_opencti_score,
167+
initialPatchScore: basePatch.x_opencti_score,
168+
updatePatchScore: updatePatch.x_opencti_score,
169+
},
170+
);
150171
}
151172
}
152173

0 commit comments

Comments
 (0)