Skip to content

Fix security, performance, and reliability issues#1

Open
tankBug wants to merge 14 commits intomainfrom
fix/code-review-improvements
Open

Fix security, performance, and reliability issues#1
tankBug wants to merge 14 commits intomainfrom
fix/code-review-improvements

Conversation

@tankBug
Copy link
Copy Markdown
Collaborator

@tankBug tankBug commented Mar 23, 2026

Summary

  • Security: Fix NoQL injection in storage queries, tighten repo permissions (authenticated users → READ only), escape HTML in widget, use serviceUrl() instead of hardcoded path
  • Performance: Fix N+1 query pattern in lookupResults with batch query + batch conn.get(), batch node fetching in searchLocalResults and lookupResultsByContributor
  • Reliability: Add task progress reporting, retry logic (2 retries w/ 5s delay) for NVA API failures, stale data cleanup (markStaleResults), correct DST-aware timezone (Europe/Oslo)
  • Cleanup: Remove dead code (fetchNvaResult, getAllResultNodeNames, ImportTaskConfig), emit events on modify, use Thread.sleep instead of busy-wait

Test plan

  • Deploy to sandbox and trigger manual import via widget
  • Verify progress is visible in Content Studio task manager during import
  • Verify stale results are marked after a full import completes
  • Verify widget link works correctly (uses dynamic serviceUrl)
  • Confirm authenticated non-admin users cannot modify NVA repo nodes

🤖 Generated with Claude Code

- Fix NoQL injection: escape single quotes in all query interpolations
- Fix N+1 queries: batch lookupResults with single query + batch conn.get()
- Add stale data cleanup: mark nodes as removedFromNva after full import
- Add task progress reporting via lib-xp-task progress()
- Add retry logic (2 retries with 5s delay) for NVA API failures
- Tighten repo permissions: role:system.authenticated reduced to READ only
- Fix widget: use serviceUrl() instead of hardcoded path, escape HTML output
- Fix timezone: GMT+1:00 → Europe/Oslo for correct DST handling
- Improve change detection: check modifiedDate before JSON comparison
- Emit custom.nva.result.modify events on updates
- Remove dead code: fetchNvaResult, getAllResultNodeNames, ImportTaskConfig
- Use java.lang.Thread.sleep instead of busy-wait for retry delay

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tankBug tankBug assigned JozoSalt and unassigned JozoSalt Mar 23, 2026
@tankBug tankBug requested a review from JozoSalt March 23, 2026 10:09
tankBug and others added 13 commits March 24, 2026 14:56
Offset pagination (page=0,1,2...) caused ~13% duplicate results and
~15% missed publications due to OpenSearch index shifting between
requests. Using nextSearchAfterResults cursor links eliminates both
issues — tested: 7,641 unique results with 0 duplicates vs 6,523
with the old approach.

Also refactored client.ts to use a loop for query param mapping
instead of 21 individual if-statements.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The codegen output is typically included in the repo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- tsconfig: Remove *.d.ts exclude, add /lib/http-client path mapping
- http-client.d.ts: Use export syntax instead of declare module
- contexts.ts: Type principals as PrincipalKey[]
- repos.ts: Use AccessControlEntry type, add generics to conn.modify/get
- xp.d.ts: Add XP.Request and XP.Response global type declarations
- gradlew: Set executable permission for Unix systems

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tibility

- Replace dashboard widget with admin tool (admin/tools/nva-import) showing
  repo stats, institution config, and manual import trigger
- Add CustomSelector services: person, funding, result-category for Content Studio
- Add site.xml to enable cross-app service access from xp-niva
- Fix storage query paths to use entityDescription.* for stored node structure
- Fix utility functions (getResultTitle, getPublicationYear, getCristinId) to
  handle both flattened NvaResult type and actual stored structure
- Fix nva-result service: resolve Untitled/Publication display, extract
  publicationInstance.type from entityDescription, return body as object
- Fix funding service: extract source label from nested object
- Replace ES6 methods (.find, .includes, Map, Array.from) with ES5 equivalents
  for Nashorn compatibility
- Remove unused barrel exports from index.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ve unused import

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…review

- Fix NoQL injection in person lookupByIds (validate numeric + use filters)
- Batch N+1 queries in person and funding services (single conn.get call)
- Add count/query parameter validation with upper bounds on all services
- Fix import task: don't increment page on failure, validate cursor URL domain
- Add entityDescription + fundings to NvaResult type (match actual stored data)
- Remove unsafe type casts in utils.ts and nva-result.ts
- Add safety threshold to markStaleResults (skip if <50% imported)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace Object.hasOwn() with hasOwnProperty.call() for Nashorn compat
- Add index signature to NvaResult for Record<string, unknown> assignability
- Normalize backslashes in check.js glob patterns for Windows support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Simplifies both the import logic and all query code — no need to
filter out stale results everywhere. The 50% safety threshold
still prevents mass deletion from incomplete imports.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

2 participants