Repository navigation
feat(assets): CSV import of the asset inventory #861
Copy link
Copy link
Closed
Labels
area:backendGo, /internal, /pkgGo, /internal, /pkgarea:frontendReact, /srcReact, /srcarea:riskRisk intelligence and quantificationRisk intelligence and quantificationdata-importpriority:P2NormalNormalpriority:P2-mediumNormal milestone workNormal milestone workstatus:in-reviewPR openPR opentier:1-product-engineProduct engine: the canonical model and the data planeProduct engine: the canonical model and the data planetype:featureNew user-facing capabilityNew user-facing capability
Milestone
Description
Activity
- addedarea:riskRisk intelligence and quantificationRisk intelligence and quantificationtype:featureNew user-facing capabilityNew user-facing capabilitypriority:P2NormalNormalarea:backendGo, /internal, /pkgGo, /internal, /pkgarea:frontendReact, /srcReact, /srcpriority:P2-mediumNormal milestone workNormal milestone workstatus:in-progressAn agent is working itAn agent is working ittier:1-product-engineProduct engine: the canonical model and the data planeProduct engine: the canonical model and the data plane
on Oct 1, 2026 - addedstatus:in-reviewPR openPR openand removedstatus:in-progressAn agent is working itAn agent is working it
on Oct 1, 2026 backend-go + frontend-react — 2026-10-01
Done
- Backend:
backend/internal/application/asset/import_assets.go(+_test.go),CreateAssetInput.Source(create_asset.go),repository.RunAssetTx/ListAssetNames(gorm_asset_repository.go),backend/internal/handler/asset_import_handler.go(+asset_import_test.go), routePOST /assets/importincmd/server/main.go(assets:create + capAssets + whole-file capacity). - Frontend:
frontend/src/features/assets/ImportAssetsPage.tsxon the sharedshared/csvImport/CsvImportPagefrom fix(risks): working, all-or-nothing CSV import of risks (#755) #859, template inimportAssetsTemplate.ts, routeassets/importinApp.tsx, Import button inInventoryPage.tsx, strings undercsvImport.assets/csvImport.errorsinlocales/{fr,en}.json.
Verified
go test ./... -count=1→ 79 ok, 0 FAIL; re-run of asset/risk/handler/repository/cmd after the final merge → ok.tsc -bok; eslint ok;vitest run→ 103 files, 953 tests passed (i18n ratchet, parity and orphan audit included).- Live on Postgres + Vite (French UI): bad file → 422 with line/column/code, nothing written; French Excel export → 3 assets
source=IMPORT; re-import → 422asset_exists× 3; a risk file naming them → scores 9.0 / 1.5 / 3.0.
Criteria — 1 ✅ · 2 ✅ · 3 ✅ · 4 ✅ · 5 ✅ · 6 ✅ · 7 ✅ · 8 ✅
Next — owner: merge in order #855 → #859 → #862.
Blocked on — merge of #855 and #859- Backend:
- linked a pull request that will close this issuefeat(assets): CSV import of the asset inventory (#861) #862
on Oct 2, 2026 - added a commit that references this issue
on Oct 2, 2026
Metadata
Metadata
Assignees
Labels
area:backendGo, /internal, /pkgGo, /internal, /pkgarea:frontendReact, /srcReact, /srcarea:riskRisk intelligence and quantificationRisk intelligence and quantificationdata-importpriority:P2NormalNormalpriority:P2-mediumNormal milestone workNormal milestone workstatus:in-reviewPR openPR opentier:1-product-engineProduct engine: the canonical model and the data planeProduct engine: the canonical model and the data planetype:featureNew user-facing capabilityNew user-facing capability
Problem
A team moving to OpenRisk already has its asset inventory in a spreadsheet. Today the only way in is the form, one asset at a time. #755 lets the risk import link risks to assets by name, which makes the gap more visible: you have to type every asset by hand before your risk file can reference it. The original stub (
internal/service/migration_service.go,TODO: Implement actual asset import logic) was never reachable, and the #755 audit split asset import out.Acceptance criteria
POST /assets/import(multipartfile, CSV) is mounted behindasset:createandcapAssets, and is scoped to the session'stenant_id. Tenant and author never come from the request.name(required, ≤ 255),type,criticality(LOW/MEDIUM/HIGH/CRITICAL, case-insensitive, plus the FrenchFAIBLE/MOYENNE/ÉLEVÉE/CRITIQUE; defaultMEDIUM),owner. Unknown columns are refused and named. Typedcategory/attributes are out of scope.line,column,code,paramsandmessage, in the same contract as fix(risks): CSV import of risks and assets fails silently #755. A valid file is written in one transaction throughCreateAssetUseCase.limit_reached). Nothing is written.;delimiter, 1000 rows / 2 MB max.created > 0.asset:create→ 403), NotFound (no file), cross-tenant (rows land only in the caller's tenant; another tenant's names do not count as duplicates).Definition of Done
Criteria 1–8 verified by tests and by a live pass on Postgres. PR open with
Closes #<n>, stacked on #859.