Skip to content

Fix/import identifications - #928

Merged
agustingroh merged 3 commits into
mainfrom
fix/import-identifications
Jul 6, 2026
Merged

Fix/import identifications#928
agustingroh merged 3 commits into
mainfrom
fix/import-identifications

Conversation

@agustingroh

@agustingroh agustingroh commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added an “Include dependencies” option when importing project knowledge.
    • Preview now shows dependency results alongside inventories, with updated table headers and localized labels.
    • Dependency matches can be reused during import, including manifest path and PURL-based matching.
  • Bug Fixes

    • Fixed crashes during dependency import flows.
    • Improved handling for dependencies without a license so imports complete more reliably.
  • Documentation

    • Updated the release notes for version 1.41.0.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a feature to import dependency identifications from another project alongside inventories: new API types, database queries, extraction/adapter logic, a new reuse task, IPC handler/service wiring, and a renderer UI checkbox with a dependencies preview table. Includes bug fixes, i18n strings, changelog, and version bump.

Changes

Dependency Identification Import Feature

Layer / File(s) Summary
Types and DTO contracts
src/api/types.ts
Adds DependencyExtraction, DependencyKnowledgeExtraction, ProjectKnowledgeExtractionResult interfaces; extends ExtractFromProjectDTO with includeDependencies and ReuseIdentificationTaskDTO with dependencyKnowledgeExtraction.
Database queries and model
src/main/model/querys_db.ts, src/main/model/queryBuilder/QueryBuilderMD5FileIn.ts, src/main/model/project/models/ProjectKnowledgeModel.ts
Fixes inventory correlation query, adds SQL_GET_KNOWLEDGE_DEPENDENCIES, fixes alias bug in f.md5_file, adds extractProjectDependencyData method.
Extraction and adapter
src/main/modules/projectKnowledge/ProjectKnowledgeExtractor.ts, src/main/modules/projectKnowledge/projectKnowledgeAdapters/projectKnowledgeAdapter.ts
Returns inventories plus optional dependencies from extraction; adds dependencyToDependencyKnowledgeExtraction adapter deduplicating dependency entries.
Reuse task and acceptance fixes
src/main/task/reuseIdentification/ReuseDependencyIdentificationTask.ts, src/main/task/reuseIdentification/ReuseIdentificationTask.ts, src/main/services/DependencyService.ts
Adds ReuseDependencyIdentificationTask matching/updating local dependencies; fixes acceptAllByIds license array payload; fixes createNewInventories file mapping for empty entries.
Service and handler wiring
src/main/services/ProjectService.ts, src/api/handlers/project.handler.ts, src/api/services/project.service.ts
Wires ProjectKnowledgeExtractionResult type, invokes new task conditionally, triggers treeService.updateDependencyStatusOnTree() after acceptance.
UI for dependency import
src/renderer/ui/dialog/ProjectSelectorDialog.tsx
Adds "Include dependencies" checkbox, dependency preview table, validation and submission logic updates.
Changelog, versioning, i18n
CHANGELOG.md, release/app/package.json, assets/i18n/*/Common.json, assets/i18n/*/Table.json, assets/i18n/*/Title.json
Adds 1.41.0 changelog entry, bumps version, adds translation strings across five locales.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ProjectSelectorDialog
  participant ProjectService
  participant ProjectKnowledgeExtractor
  participant ReuseDependencyIdentificationTask
  participant DependencyService

  ProjectSelectorDialog->>ProjectService: extractInventoryKnowledge(includeDependencies=true)
  ProjectService->>ProjectKnowledgeExtractor: extractInventoryData()
  ProjectKnowledgeExtractor-->>ProjectService: inventories + dependencies
  ProjectService-->>ProjectSelectorDialog: ProjectKnowledgeExtractionResult
  ProjectSelectorDialog->>ProjectService: acceptInventoryKnowledge(dependencyKnowledgeExtraction)
  ProjectService->>ReuseDependencyIdentificationTask: run()
  ReuseDependencyIdentificationTask->>DependencyService: acceptAllByIds(accepted dependencies)
  ReuseDependencyIdentificationTask-->>ProjectService: done
  ProjectService-->>ProjectSelectorDialog: accepted inventories
Loading

Possibly related PRs

  • scanoss/sbom-workbench#891: Both PRs modify extractInventoryData in ProjectKnowledgeExtractor.ts, with this PR extending its return payload to include dependencies.

Suggested labels: enhancement

Suggested reviewers: isasmendiagus, scanoss-qg

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and refers to the main theme of importing identifications, which matches the core changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/import-identifications

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: dependency version conflict. Check your lock file or package.json.


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

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/main/task/reuseIdentification/ReuseIdentificationTask.ts (1)

72-81: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use a surviving file id for source.input. fileMapper.get(Object.keys(this.reuseIdentification.inventoryKnowledgeExtraction)[0]) can still be undefined when the first extraction key has no local match. In overwrite mode that value reaches Restore, where QueryBuilderFileIdIn calls .toString() on it and throws.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/task/reuseIdentification/ReuseIdentificationTask.ts` around lines 72
- 81, Update ReuseIdentificationTask so the Accept source.input never relies on
a possibly missing fileMapper lookup when overwrite is enabled; the current
fileMapper.get(Object.keys(this.reuseIdentification.inventoryKnowledgeExtraction)[0])
path can yield undefined and later break Restore via QueryBuilderFileIdIn. Use a
surviving file id or a safe fallback derived from the available
inventories/extraction keys inside ReuseIdentificationTask before constructing
the Accept input, and keep the PATH branch unchanged.
src/main/services/DependencyService.ts (1)

207-214: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Attach the dependency’s licenses to matched components src/main/services/DependencyService.ts:207-214
comp.licenses is the component’s already-attached set, so this branch filters those licenses out and leaves attach empty for normal existing-component matches. Use the incoming dependency’s d.licenses here, then diff against the component’s current attachments before calling attachLicensesToComponentBulk.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/services/DependencyService.ts` around lines 207 - 214, The
attachment logic in DependencyService uses the component’s existing licenses
instead of the dependency’s incoming licenses, so matched components never get
new licenses attached. Update the forEach branch in DependencyService to build
the attachment list from d.licenses, compare against the component’s current
license attachments via licenseMapper, and then pass the resulting ids into
attachLicensesToComponentBulk using the existing compid/attach flow.
🧹 Nitpick comments (1)
src/main/modules/projectKnowledge/ProjectKnowledgeExtractor.ts (1)

19-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Stale JSDoc return type.

The doc comment still says @return InventoryKnowledgeExtraction, but the method now returns ProjectKnowledgeExtractionResult.

   /**
   * `@brief` extracts the inventory data from external projects
-  * `@return` InventoryKnowledgeExtraction
+  * `@return` ProjectKnowledgeExtractionResult
   * */
   public async extractInventoryData():Promise<ProjectKnowledgeExtractionResult> {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/modules/projectKnowledge/ProjectKnowledgeExtractor.ts` around lines
19 - 41, Update the JSDoc for extractInventoryData so the documented return type
matches the actual ProjectKnowledgeExtractionResult returned by the method. Keep
the comment aligned with the function signature and its returned
inventories/dependencies object, and remove the stale
InventoryKnowledgeExtraction type reference.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/api/handlers/project.handler.ts`:
- Around line 223-225: The PROJECT handler is triggering async dependency status
updates without waiting for completion, so the response can be sent before tree
status changes are persisted. Update the logic around
treeService.updateDependencyStatusOnTree() in project.handler.ts to await the
call (and any returned promise chain) before continuing, so updateDone()
completes before the handler finishes and PROJECT_READ_TREE sees fresh status.

In `@src/main/model/project/models/ProjectKnowledgeModel.ts`:
- Around line 41-49: In extractProjectDependencyData, the LIKE filter is
building SQL by interpolating folder directly, which is vulnerable to malformed
paths and wildcard over-matching. Update the query construction to bind folder
as a parameter instead of string concatenation, and escape any % or _ characters
in the folder value before adding the trailing % pattern so only the intended
subtree matches.

In `@src/main/task/reuseIdentification/ReuseDependencyIdentificationTask.ts`:
- Around line 36-48: In ReuseDependencyIdentificationTask’s localDependencies
processing, the current guard only skips FileStatusType.IDENTIFIED entries when
overwrite is false, so ORIGINAL/rejected dependencies can still be re-imported
and unintentionally un-rejected. Update the filtering logic in the forEach block
to treat ORIGINAL the same as IDENTIFIED unless this.params.overwrite is true,
keeping rejected entries untouched unless an overwrite is explicitly requested.

---

Outside diff comments:
In `@src/main/services/DependencyService.ts`:
- Around line 207-214: The attachment logic in DependencyService uses the
component’s existing licenses instead of the dependency’s incoming licenses, so
matched components never get new licenses attached. Update the forEach branch in
DependencyService to build the attachment list from d.licenses, compare against
the component’s current license attachments via licenseMapper, and then pass the
resulting ids into attachLicensesToComponentBulk using the existing
compid/attach flow.

In `@src/main/task/reuseIdentification/ReuseIdentificationTask.ts`:
- Around line 72-81: Update ReuseIdentificationTask so the Accept source.input
never relies on a possibly missing fileMapper lookup when overwrite is enabled;
the current
fileMapper.get(Object.keys(this.reuseIdentification.inventoryKnowledgeExtraction)[0])
path can yield undefined and later break Restore via QueryBuilderFileIdIn. Use a
surviving file id or a safe fallback derived from the available
inventories/extraction keys inside ReuseIdentificationTask before constructing
the Accept input, and keep the PATH branch unchanged.

---

Nitpick comments:
In `@src/main/modules/projectKnowledge/ProjectKnowledgeExtractor.ts`:
- Around line 19-41: Update the JSDoc for extractInventoryData so the documented
return type matches the actual ProjectKnowledgeExtractionResult returned by the
method. Keep the comment aligned with the function signature and its returned
inventories/dependencies object, and remove the stale
InventoryKnowledgeExtraction type reference.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aadc7595-d717-4cde-90b9-ee0320781f8d

📥 Commits

Reviewing files that changed from the base of the PR and between 0658fef and f956289.

📒 Files selected for processing (30)
  • CHANGELOG.md
  • assets/i18n/en/Common.json
  • assets/i18n/en/Table.json
  • assets/i18n/en/Title.json
  • assets/i18n/es/Common.json
  • assets/i18n/es/Table.json
  • assets/i18n/es/Title.json
  • assets/i18n/fr/Common.json
  • assets/i18n/fr/Table.json
  • assets/i18n/fr/Title.json
  • assets/i18n/jp/Common.json
  • assets/i18n/jp/Table.json
  • assets/i18n/jp/Title.json
  • assets/i18n/zh/Common.json
  • assets/i18n/zh/Table.json
  • assets/i18n/zh/Title.json
  • release/app/package.json
  • src/api/handlers/project.handler.ts
  • src/api/services/project.service.ts
  • src/api/types.ts
  • src/main/model/project/models/ProjectKnowledgeModel.ts
  • src/main/model/queryBuilder/QueryBuilderMD5FileIn.ts
  • src/main/model/querys_db.ts
  • src/main/modules/projectKnowledge/ProjectKnowledgeExtractor.ts
  • src/main/modules/projectKnowledge/projectKnowledgeAdapters/projectKnowledgeAdapter.ts
  • src/main/services/DependencyService.ts
  • src/main/services/ProjectService.ts
  • src/main/task/reuseIdentification/ReuseDependencyIdentificationTask.ts
  • src/main/task/reuseIdentification/ReuseIdentificationTask.ts
  • src/renderer/ui/dialog/ProjectSelectorDialog.tsx

Comment on lines +223 to +225
if (param.dependencyKnowledgeExtraction && Object.keys(param.dependencyKnowledgeExtraction).length > 0) {
treeService.updateDependencyStatusOnTree();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check TreeService.updateDependencyStatusOnTree signature/implementation
rg -n -A15 'updateDependencyStatusOnTree' src/main/services

Repository: scanoss/sbom-workbench

Length of output: 1308


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## TreeService.ts\n'
ast-grep outline src/main/services/TreeService.ts --view expanded

printf '\n## project.handler.ts\n'
ast-grep outline src/api/handlers/project.handler.ts --view expanded

printf '\n## PROJECT_READ_TREE references\n'
rg -n -A20 -B10 'PROJECT_READ_TREE|updateDependencyStatusOnTree|updateDependencyStatus\(' src

Repository: scanoss/sbom-workbench

Length of output: 22040


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## TreeService helpers\n'
sed -n '1,140p' src/main/services/TreeService.ts

printf '\n## file/dependency model write signatures\n'
rg -n -A2 -B2 'restore\(|identified\(|ignored\(|getStatus\(' src/main -g '!**/dist/**' -g '!**/build/**'

Repository: scanoss/sbom-workbench

Length of output: 19224


src/api/handlers/project.handler.ts:223-225 — Await treeService.updateDependencyStatusOnTree()
updateDependencyStatusOnTree() kicks off async work and returns immediately, so this handler can reply before the dependency status update and updateDone() finish. A subsequent PROJECT_READ_TREE can then see stale statuses.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/handlers/project.handler.ts` around lines 223 - 225, The PROJECT
handler is triggering async dependency status updates without waiting for
completion, so the response can be sent before tree status changes are
persisted. Update the logic around treeService.updateDependencyStatusOnTree() in
project.handler.ts to await the call (and any returned promise chain) before
continuing, so updateDone() completes before the handler finishes and
PROJECT_READ_TREE sees fresh status.

Comment on lines +41 to +49
public async extractProjectDependencyData(projectPath: string, folder: string){
const db = await this.openDb();
const call = await this.attach(db,projectPath);
const query = `${queries.SQL_GET_KNOWLEDGE_DEPENDENCIES} AND target.path LIKE '${folder}%';`;
const dependencies = await this.getInventories(db,query);
await call(`DETACH DATABASE aux`);
db.close();
return dependencies;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

git ls-files src/main/model/project/models/ProjectKnowledgeModel.ts src/main/model | sed -n '1,120p'

Repository: scanoss/sbom-workbench

Length of output: 2828


🏁 Script executed:

sed -n '1,220p' src/main/model/project/models/ProjectKnowledgeModel.ts

Repository: scanoss/sbom-workbench

Length of output: 2379


🏁 Script executed:

rg -n "getInventories\\(" src/main -g '*.ts'

Repository: scanoss/sbom-workbench

Length of output: 524


🏁 Script executed:

rg -n "folder" src/main -g '*.ts'

Repository: scanoss/sbom-workbench

Length of output: 14807


Bind folder instead of interpolating it into the LIKE clause, and escape %/_ before appending %. A quoted path can alter the SQL, and wildcard characters in real folder names will over-match.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/model/project/models/ProjectKnowledgeModel.ts` around lines 41 - 49,
In extractProjectDependencyData, the LIKE filter is building SQL by
interpolating folder directly, which is vulnerable to malformed paths and
wildcard over-matching. Update the query construction to bind folder as a
parameter instead of string concatenation, and escape any % or _ characters in
the folder value before adding the trailing % pattern so only the intended
subtree matches.

Comment on lines +36 to +48
localDependencies.forEach((dep: any) => {
// Skip already identified dependencies unless overwriting
if (dep.status === FileStatusType.IDENTIFIED && !this.params.overwrite) return;
const extracted = extractedByKey.get(`${dep.path}-${dep.purl}`);
if (!extracted) return;
const licenses = extracted.licenses ? extracted.licenses.split(',').filter((l) => l) : [];
// A declared dependency identification requires a license; skip incomplete ones
if (licenses.length === 0) return;
dep.version = extracted.version;
dep.licenses = licenses;
dep.scope = extracted.scope;
dependenciesToAccept.push(dep);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## FileStatusType references\n'
rg -n "FileStatusType\.(ORIGINAL|IDENTIFIED|PENDING)|rejectedAt|status\s*===\s*FileStatusType\.ORIGINAL" src -g'*.ts'

printf '\n## Candidate files\n'
git ls-files 'src/main/task/**/Reuse*Task.ts' 'src/**/FileStatusType*.ts' 'src/**/status*.ts' | sed -n '1,120p'

printf '\n## Outline of target files\n'
for f in \
  src/main/task/reuseIdentification/ReuseDependencyIdentificationTask.ts \
  src/main/task/reuseIdentification/ReuseIdentificationTask.ts
do
  if [ -f "$f" ]; then
    echo "FILE: $f"
    ast-grep outline "$f" --view expanded
  fi
done

Repository: scanoss/sbom-workbench

Length of output: 8338


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## FileStatusType references\n'
rg -n "FileStatusType\.(ORIGINAL|IDENTIFIED|PENDING)|rejectedAt|status\s*===\s*FileStatusType\.ORIGINAL" src -g'*.ts'

printf '\n## Candidate files\n'
git ls-files 'src/main/task/**/Reuse*Task.ts' 'src/**/FileStatusType*.ts' 'src/**/status*.ts' | sed -n '1,120p'

printf '\n## Target file slices\n'
for f in \
  src/main/task/reuseIdentification/ReuseDependencyIdentificationTask.ts \
  src/main/task/reuseIdentification/ReuseIdentificationTask.ts
do
  if [ -f "$f" ]; then
    echo "FILE: $f"
    sed -n '1,220p' "$f" | nl -ba | sed -n '1,220p'
  fi
done

Repository: scanoss/sbom-workbench

Length of output: 6621


🏁 Script executed:

#!/bin/bash
set -euo pipefail

set -x
rg -n "enum FileStatusType|FileStatusType" src -g'*.ts' || true
rg -n "rejectedAt" src -g'*.ts' || true
rg -n "status: FileStatusType.ORIGINAL|status === FileStatusType.ORIGINAL|FileStatusType.ORIGINAL" src -g'*.ts' || true

Repository: scanoss/sbom-workbench

Length of output: 11180


Skip ORIGINAL dependencies when overwrite is false
ORIGINAL maps to rejected entries (rejectedAt != null), so this import can silently un-reject previously rejected dependencies. Treat it like IDENTIFIED unless overwrite is enabled.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/task/reuseIdentification/ReuseDependencyIdentificationTask.ts`
around lines 36 - 48, In ReuseDependencyIdentificationTask’s localDependencies
processing, the current guard only skips FileStatusType.IDENTIFIED entries when
overwrite is false, so ORIGINAL/rejected dependencies can still be re-imported
and unintentionally un-rejected. Update the filtering logic in the forEach block
to treat ORIGINAL the same as IDENTIFIED unless this.params.overwrite is true,
keeping rejected entries untouched unless an overwrite is explicitly requested.

@agustingroh
agustingroh merged commit 5f6dcf5 into main Jul 6, 2026
4 checks passed
@agustingroh
agustingroh deleted the fix/import-identifications branch July 6, 2026 13:49
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.

1 participant