Skip to content

Conversation

@holycrab13
Copy link
Contributor

@holycrab13 holycrab13 commented Nov 6, 2025

Summary by CodeRabbit

  • New Features

    • Live navigation search with resource-type filters
    • User settings UI for account, secretaries and API key management
    • New modular publish wizard and API-based registration UI
    • Frontpage call-to-action and site banner
    • New entity API viewer and improved error notification component
  • Improvements

    • Full navigation redesign and responsive navbar
    • Overhauled visual theme, fonts, colors and frontpage layout
    • Collection/publish UIs modernized and richer validation
  • Chores

    • Deployment/dev tooling and example configurations added (local/docker)

holycrab13 and others added 24 commits July 31, 2025 13:32
…E retrieval that checks for trailing newline
…r non-jsonld resource retrieval, added tests
@coderabbitai
Copy link

coderabbitai bot commented Nov 6, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Large multi-area change adding deployment configs and dev tooling, migrating many frontend controllers/templates to an account-centric model, introducing a modular publish workflow (EntityHandler + Group/Artifact/Version handlers), adding new UI components/styles, and refactoring Docker build and compose artifacts. Changes span server env, SHACL docs/models, and many client JS/CSS/templates.

Changes

Cohort / File(s) Summary
Root & Dev config
\.dockerignore`, `.env`, `.vscode/launch.json`, `.vscode/settings.json``
Adjusted ignore patterns to include node_modules and server/node_modules; added DATABUS_ABSTRACT to .env; added VSCode launch configurations and an editor setting.
Docker & Compose
\Dockerfile`, `docker-compose.yml`, `docker-compose-4-swarm.yml`, devenv/docker-compose.yml``
Rewrote multi-stage Dockerfile using node:23-slim, simplified runtime stage, changed build/copy steps; updated compose files (service images, ports, added lookup, metrics/lookup envs) and added a Swarm compose. devenv compose contains merge-conflict fragments.
Deployment & docs
deployment/.env, deployment/README.md
Added deployment env entries for Databus and DB credentials and a short README with startup instruction.
Dev tooling & scripts
backup.sh, devenv/Makefile, devenv/random-downloader.sh, devenv/prometheus.yml, devenv/grafana-promql.md
Added backup script; Makefile additions (DATABUS_ABSTRACT, DATABUS_BANNER, dockerize target); a random downloader script; Prometheus config and Grafana query notes.
SHACL / backend models & docs
model/*.php, docs/*.md (e.g., model/account.php, model/artifact.php, docs/version.md)
Tightened IRI validation regexes, increased title length limits, added prov:wasDerivedFrom shape, and renamed account context field mapping from name to displayName; updated matching docs.
Runtime template & header refactor
public/templates/header.ejs, public/templates/nav.ejs, public/templates/banner.ejs, public/templates/variables.ejs
Extracted header/nav into partials, added new banner and variables templates to initialize client-side globals and render databus banner.
Frontpage & templates
public/templates/index.ejs, public/templates/collection-editor.ejs, public/templates/collections-editor.ejs, public/templates/download.ejs, others`
Reworked frontpage with CTA boxes; removed outdated download.ejs; replaced some create-account flows with error messaging for missing local collections; assorted small template cleanups.
CSS / visual system
public/css/_colors.scss, _components.scss, _entities.scss, _fonts.scss, _nav.scss, _frontpage.scss, _sparql.scss, website.scss, website.css
New color tokens (navbar, banner, backgrounds), new fonts, multiple new component/layout styles (navbar, frontpage boxes, utilities), entity color updates and many style restructures.
Angular app registration
public/js/angular-application.js, public/js/search/search-manager.js
Registered new controllers/components (UserSettingsController, NavSearchController, EntityDropdown, EntityApiView, ErrorNotification, navSearch); disabled account-data fetch block in search-manager.
New UI components
public/js/components/* (e.g., entity-dropdown, entity-api-view, error-notification, databus-icon, entity-card, nav-search, etc.)
Added multiple reusable components and templates: entity dropdown with search, API view (register / cURL), error tag, nav search controller and template, updated databus-icon paths and sizing, entity card/content updates.
Collections & client models
public/js/collections/databus-collection-manager.js, public/js/collections/databus-collection-wrapper.js
Made collection manager account-aware: init lifecycle, isInitialized/subscribers, accountName guards, tryInitialize remote sync; wrapper.createNew now accepts accountName.
Publishing system (client)
public/js/publish/* (e.g., entity-handler.js, group-data.js, artifact-data.js, version-handler.js, publish-session.js, publish-data.js, databus-sparql-client.js)
New modular publish architecture: EntityHandler base, Group/Artifact/Version handlers with validation/updateOutputs, SPARQL client for lookups, PublishSession refactor, PublishData adjusted to account. Adds register()/curl generation and session persistence.
Page controllers (account/profile/publish/etc.)
public/js/page-controller/* (notable: account-controller.js, profile-controller.js, user-settings-controller.js, publish-wizard-controller.js, collections-editor-controller.js, version-controller.js, sparql-editor-controller.js)
Migrated many controllers from profileData to account/accountName model; added user-settings controller; some controllers became async or gained $location; publish wizard refactored to use TabNavigation and account lists; several controllers switched update endpoints to /api/register.
Publish UI templates & wizard
public/templates/publish-wizard.ejs, public/templates/publish-wizard-old.ejs, public/templates/publish-wizard copy.ejs
Reworked publishing UI into modular/tabbed wizard layouts, added entity-api-view and error-tag integration, added advanced file/content-variant management templates (multiple wizard variants present).
Utility libraries
public/js/utils/* (e.g., app-json-formatter.js, databus-uris.js, databus-utils.js, databus-webapp-utils.js, jsonld-utils.js, messages.js, tab-navigation.js)
Added centralized messages, new DatabusUris constants (account/secretary URIs), account graph creation helpers, JSON‑LD helpers, resemblesTrue/getFirstSegment, getAccountName/goTo, TabNavigation callback extension.
Templates: account/profile/settings
public/templates/account.ejs, public/templates/profile.ejs, public/templates/user-settings.ejs
Converted templates to account-based bindings, added Secretaries management and a DANGER ZONE (delete account) in profile, added user-settings UI.
Misc small behavioral/UI changes
many files (e.g., result ID usage changes: result.resource[...]result.id[...], table-editor edits, file-browser auth gating)
Standardized search/result URI usage to result.id[...]; table-editor moved from table to flex-grid and uses cv.id; collection-editor widget gated by authentication; various small controller/template adjustments.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant UI as Collections Editor UI
    participant CM as CollectionManager
    participant API as Databus API
    participant Storage as Local/Session Storage

    User->>UI: Open collection editor (uuid)
    UI->>CM: tryInitialize(accountName)
    activate CM
    CM->>Storage: load local collections for accountName
    CM->>API: fetch remote collections
    API-->>CM: return collections
    CM->>Storage: materialize missing local copies
    CM->>CM: _notifyInitialized()
    deactivate CM
    CM-->>UI: initialized
    UI->>CM: setActive(uuid)
    CM-->>UI: active collection ready
    User->>UI: edit & save
    UI->>Storage: save local changes
    UI-->>User: save confirmation
Loading
sequenceDiagram
    autonumber
    participant User
    participant PW as Publish Wizard UI
    participant PS as PublishSession
    participant SC as DatabusSparqlClient
    participant Handler as EntityHandler (Group/Artifact/Version)
    participant API as /api/register

    User->>PW: select account
    PW->>PS: selectAccount(account)
    activate PS
    PS->>SC: getGroups(accountName)
    SC->>API: SPARQL query
    API-->>SC: groups
    PS->>PS: persist selection
    deactivate PS
    User->>PW: choose/create group
    PW->>PS: selectGroup/createNewGroup
    PS->>Handler: initialize group data
    Handler->>PS: updateOutputs() (generate JSON-LD + curl)
    User->>PW: register entity
    PW->>API: POST /api/register (with API key)
    API-->>PW: success/error
    PW-->>User: show result
Loading
sequenceDiagram
    autonumber
    participant Client
    participant Nav as NavSearchController
    participant SM as SearchManager
    participant API as Search API

    Client->>Nav: type query
    Nav->>Nav: set searchChanged=true
    Nav->>Nav: interval loop triggers
    Nav->>SM: set query formatter and filters
    Nav->>SM: execute search
    SM->>API: POST search request
    API-->>SM: results
    SM-->>Nav: results
    Nav->>Client: render results (uses result.id[])
    Client->>Nav: click result -> navigateTo(result.id)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Specific areas to review carefully:

  • databus-collection-manager.js — account-aware lifecycle, new public APIs and guards, remote/local sync.
  • Publish system: public/js/publish/* (entity-handler.js, publish-session.js, group-data.js, artifact-data.js, version-handler.js) — new abstractions, session persistence, SPARQL client integration, duplicate method definitions noted in EntityHandler.
  • Controllers migrating to account model — ensure template bindings and controller scope properties (account/accountName/auth) align across templates.
  • Dockerfile and compose files — multi-stage build changes and unresolved merge-conflict markers in devenv/docker-compose.yml.
  • Endpoint semantics — controllers now POST to /api/register instead of previous PUT flows; confirm backend compatibility.
  • Large CSS/templating additions — visual regressions, missing partial includes, and component wiring (new components/templates referenced by controllers).
  • Utilities with API changes — app-json-formatter, jsonld-utils, new DatabusUris/constants: validate consumers expecting the old shapes.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22dbf26 and 62cbdc1.

⛔ Files ignored due to path filters (20)
  • model/generated/context.json is excluded by !**/generated/**
  • model/generated/shacl/account.shacl is excluded by !**/generated/**
  • model/generated/shacl/artifact.shacl is excluded by !**/generated/**
  • model/generated/shacl/collection.shacl is excluded by !**/generated/**
  • model/generated/shacl/group.shacl is excluded by !**/generated/**
  • model/generated/shacl/version.shacl is excluded by !**/generated/**
  • public/dist/main.js is excluded by !**/dist/**
  • public/fonts/Inter-Black.ttf is excluded by !**/*.ttf
  • public/fonts/Inter-Bold.ttf is excluded by !**/*.ttf
  • public/fonts/Inter-ExtraBold.ttf is excluded by !**/*.ttf
  • public/fonts/Inter-ExtraLight.ttf is excluded by !**/*.ttf
  • public/fonts/Inter-Light.ttf is excluded by !**/*.ttf
  • public/fonts/Inter-Medium.ttf is excluded by !**/*.ttf
  • public/fonts/Inter-Regular.ttf is excluded by !**/*.ttf
  • public/fonts/Inter-SemiBold.ttf is excluded by !**/*.ttf
  • public/fonts/Inter-Thin.ttf is excluded by !**/*.ttf
  • public/fonts/Roboto-Bold.ttf is excluded by !**/*.ttf
  • public/fonts/Roboto-Regular.ttf is excluded by !**/*.ttf
  • search/lookup-indexer.jar is excluded by !**/*.jar
  • search/lookup-server.jar is excluded by !**/*.jar
📒 Files selected for processing (107)
  • .dockerignore (1 hunks)
  • .env (1 hunks)
  • .vscode/launch.json (1 hunks)
  • .vscode/settings.json (1 hunks)
  • Dockerfile (1 hunks)
  • backup.sh (1 hunks)
  • deployment/.env (1 hunks)
  • deployment/README.md (1 hunks)
  • deployment/docker-compose.yml (1 hunks)
  • devenv/Makefile (4 hunks)
  • devenv/README.md (1 hunks)
  • devenv/docker-compose.yml (2 hunks)
  • devenv/grafana-promql.md (1 hunks)
  • devenv/prometheus.yml (1 hunks)
  • devenv/random-downloader.sh (1 hunks)
  • docker-compose-4-swarm.yml (1 hunks)
  • docker-compose.yml (3 hunks)
  • docs/account.md (1 hunks)
  • docs/artifact.md (2 hunks)
  • docs/group.md (2 hunks)
  • docs/version.md (3 hunks)
  • model/account.php (1 hunks)
  • model/artifact.php (2 hunks)
  • model/finalize.php (1 hunks)
  • model/group.php (2 hunks)
  • model/version.php (3 hunks)
  • public/css/_colors.scss (2 hunks)
  • public/css/_components.scss (4 hunks)
  • public/css/_entities.scss (3 hunks)
  • public/css/_fonts.scss (1 hunks)
  • public/css/_frontpage.scss (1 hunks)
  • public/css/_nav.scss (1 hunks)
  • public/css/_sparql.scss (1 hunks)
  • public/css/website.css (153 hunks)
  • public/css/website.scss (6 hunks)
  • public/js/angular-application.js (7 hunks)
  • public/js/collections/databus-collection-manager.js (22 hunks)
  • public/js/collections/databus-collection-wrapper.js (1 hunks)
  • public/js/components/collection-hierarchy-two/collection-hierarchy.html (2 hunks)
  • public/js/components/collection-hierarchy-two/collection-hierarchy.js (2 hunks)
  • public/js/components/collection-search/collection-search.html (1 hunks)
  • public/js/components/collection-search/collection-search.js (2 hunks)
  • public/js/components/databus-icon/databus-icon.html (1 hunks)
  • public/js/components/databus-icon/databus-icon.js (2 hunks)
  • public/js/components/entity-api-view/entity-api-view.html (1 hunks)
  • public/js/components/entity-api-view/entity-api-view.js (1 hunks)
  • public/js/components/entity-card/entity-card.html (2 hunks)
  • public/js/components/entity-dropdown/entity-dropdown.html (1 hunks)
  • public/js/components/entity-dropdown/entity-dropdown.js (1 hunks)
  • public/js/components/error-notification/error-notifcation.js (1 hunks)
  • public/js/components/error-notification/error-notification.html (1 hunks)
  • public/js/components/facets-view/facets-view.js (9 hunks)
  • public/js/components/file-browser/file-browser.html (1 hunks)
  • public/js/components/nav-search/nav-search-controller.js (1 hunks)
  • public/js/components/nav-search/nav-search.html (1 hunks)
  • public/js/components/search/search-controller.js (1 hunks)
  • public/js/components/search/search.html (1 hunks)
  • public/js/components/table-editor/table-editor.html (3 hunks)
  • public/js/components/table-editor/table-editor.js (6 hunks)
  • public/js/components/type-tag/type-tag.js (2 hunks)
  • public/js/page-controller/account-controller.js (11 hunks)
  • public/js/page-controller/artifact-controller.js (3 hunks)
  • public/js/page-controller/collection-controller.js (4 hunks)
  • public/js/page-controller/collections-editor-controller.js (2 hunks)
  • public/js/page-controller/frontpage-controller.js (1 hunks)
  • public/js/page-controller/group-controller.js (7 hunks)
  • public/js/page-controller/header-controller.js (1 hunks)
  • public/js/page-controller/profile-controller.js (10 hunks)
  • public/js/page-controller/publish-wizard-controller.js (6 hunks)
  • public/js/page-controller/sparql-editor-controller.js (5 hunks)
  • public/js/page-controller/user-settings-controller.js (1 hunks)
  • public/js/page-controller/version-controller.js (6 hunks)
  • public/js/publish/artifact-data.js (1 hunks)
  • public/js/publish/databus-sparql-client.js (1 hunks)
  • public/js/publish/entity-handler.js (1 hunks)
  • public/js/publish/group-data.js (1 hunks)
  • public/js/publish/publish-data.js (5 hunks)
  • public/js/publish/publish-session.js (10 hunks)
  • public/js/publish/version-handler.js (1 hunks)
  • public/js/search/search-manager.js (2 hunks)
  • public/js/utils/app-json-formatter.js (4 hunks)
  • public/js/utils/databus-messages.js (1 hunks)
  • public/js/utils/databus-uris.js (2 hunks)
  • public/js/utils/databus-utils.js (7 hunks)
  • public/js/utils/databus-webapp-utils.js (1 hunks)
  • public/js/utils/jsonld-utils.js (4 hunks)
  • public/js/utils/messages.js (1 hunks)
  • public/js/utils/tab-navigation.js (2 hunks)
  • public/templates/404.ejs (1 hunks)
  • public/templates/account.ejs (7 hunks)
  • public/templates/artifact.ejs (1 hunks)
  • public/templates/banner.ejs (1 hunks)
  • public/templates/collection-editor.ejs (1 hunks)
  • public/templates/collections-editor.ejs (1 hunks)
  • public/templates/download.ejs (0 hunks)
  • public/templates/group.ejs (0 hunks)
  • public/templates/header.ejs (2 hunks)
  • public/templates/index.ejs (2 hunks)
  • public/templates/nav.ejs (1 hunks)
  • public/templates/profile.ejs (5 hunks)
  • public/templates/publish-wizard copy.ejs (1 hunks)
  • public/templates/publish-wizard-old.ejs (1 hunks)
  • public/templates/publish-wizard.ejs (1 hunks)
  • public/templates/sparql-editor.ejs (3 hunks)
  • public/templates/unauthorized.ejs (3 hunks)
  • public/templates/user-settings.ejs (1 hunks)
  • public/templates/variables.ejs (1 hunks)
⛔ Files not processed due to max files limit (45)
  • search/Dockerfile
  • search/docker-compose.yml
  • search/gstore-helper.js
  • search/index-config.yml
  • search/indexer/account.yml
  • search/indexer/artifact.yml
  • search/indexer/collection.yml
  • search/indexer/group.yml
  • search/indexer/version.yml
  • search/servlet-config.yml
  • server/app/api/lib/account-writer.js
  • server/app/api/lib/artifact-writer.js
  • server/app/api/lib/collection-writer.js
  • server/app/api/lib/databus-tractate-suite.js
  • server/app/api/lib/dataid-autocomplete.js
  • server/app/api/lib/group-writer.js
  • server/app/api/lib/gstore-resource.js
  • server/app/api/lib/publish-account.js
  • server/app/api/lib/publish-artifact.js
  • server/app/api/lib/publish-group.js
  • server/app/api/lib/publish-version.js
  • server/app/api/lib/resource-writer.js
  • server/app/api/module.js
  • server/app/api/routes/account.js
  • server/app/api/routes/artifact.js
  • server/app/api/routes/collection.js
  • server/app/api/routes/general.js
  • server/app/api/routes/group.js
  • server/app/api/routes/version.js
  • server/app/api/statistics/metrics-manager.js
  • server/app/api/swagger-client.js
  • server/app/api/swagger-page.js
  • server/app/api/swagger.yml
  • server/app/api/webdav.js
  • server/app/app.js
  • server/app/common/404.js
  • server/app/common/constants.js
  • server/app/common/databus-logger.js
  • server/app/common/databus-message.js
  • server/app/common/databus-resource.js
  • server/app/common/execute-construct.js
  • server/app/common/execute-query.js
  • server/app/common/get-jsonld.js
  • server/app/common/get-linked-data.js
  • server/app/common/protect/middleware.js

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 and usage tips.

@holycrab13 holycrab13 merged commit 21e4fcb into master Nov 6, 2025
2 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 62

Caution

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

⚠️ Outside diff range comments (7)
public/js/search/search-manager.js (1)

62-89: Remove or restore the search extension initialization code.

The commented block disables loading of user-configured search extensions at initialization, creating an inconsistency: while the profile controller UI permits users to add/remove search extensions, the SearchManager.initialize() method never loads them. Only the base /api/search adapter will be available at runtime.

Either uncomment and test the initialization logic (lines 62-89), or remove it entirely along with the related UI functions in profile-controller.js (addSearchExtension, removeSearchExtension) to avoid user confusion. If this is a known limitation or deprecated feature, document it in a comment explaining why custom extensions are not loaded.

public/js/page-controller/version-controller.js (1)

106-141: Fix variable redeclaration.

Line 141 redeclares response, which shadows the previous declaration at line 114. This can lead to confusion and potential bugs.

Apply this diff to fix the issue:

-      var response = await $http.put(`/api/register`, graphs);
+      response = await $http.put(`/api/register`, graphs);
devenv/docker-compose.yml (1)

40-44: Fix SQL grant initialization bug.

Line 43 uses > (overwrite) instead of >> (append), which overwrites the previous grants from lines 41-42. This results in only SPARQL_SELECT_FED being granted, while SPARQL_LOAD_SERVICE_DATA and SPARQL_SPONGE are lost.

Apply this diff to fix the grant initialization:

    entrypoint: /bin/bash -c "
        echo 'grant SPARQL_LOAD_SERVICE_DATA to \"SPARQL\";' > /opt/virtuoso-opensource/initdb.d/ini.sql &&
        echo 'grant SPARQL_SPONGE to \"SPARQL\";' >> /opt/virtuoso-opensource/initdb.d/ini.sql &&
-        echo 'grant SPARQL_SELECT_FED to \"SPARQL\";' > /opt/virtuoso-opensource/initdb.d/ini.sql &&
+        echo 'grant SPARQL_SELECT_FED to \"SPARQL\";' >> /opt/virtuoso-opensource/initdb.d/ini.sql &&
        /virtuoso-entrypoint.sh"
public/js/page-controller/collection-controller.js (1)

71-82: Fix the malformed editor URL query string.

Both editCopy and createSnapshot drop the = before uuid, so we now navigate to /app/collection-editor?uuid123 instead of /app/collection-editor?uuid=123, breaking the editor route. Please reintroduce the = for both redirects.

-    window.location.href = `/app/collection-editor?uuid${localCopy.uuid}`;
+    window.location.href = `/app/collection-editor?uuid=${localCopy.uuid}`;
...
-    window.location.href = `/app/collection-editor?uuid${collectionSnapshot.uuid}`;
+    window.location.href = `/app/collection-editor?uuid=${collectionSnapshot.uuid}`;
public/js/page-controller/group-controller.js (1)

68-84: Restore the ownership check before enabling edit mode.

canEdit now only checks that accountName is non-null, so every logged-in visitor sees the edit UI for someone else’s group. We must keep the owner comparison to prevent unauthorized edits.

-  $scope.canEdit = $scope.accountName != null;
+  $scope.canEdit = $scope.authenticated && $scope.auth?.info?.accountName === $scope.accountName;
public/js/page-controller/account-controller.js (1)

129-162: Collection loading logic has potential issues.

Several concerns:

  1. Lines 145-147: Parsing accountName from collection.uri using DatabusUtils.getFirstSegment() is fragile. If the URI format changes or is malformed, this could fail silently.

  2. Line 149: The comparison collection.accountName == $scope.accountName uses loose equality (==). Use strict equality (===) for type safety.

  3. Lines 157-161: The subscription pattern with isInitialized flag suggests async initialization, but there's no error handling if initialization fails or if the callback is never invoked.

Apply these improvements:

-        if(collection.accountName == undefined && collection.uri != undefined) {
+        if (collection.accountName === undefined && collection.uri !== undefined) {
           collection.accountName = DatabusUtils.getFirstSegment(collection.uri);
         }
 
-        if (collection.accountName == $scope.accountName) {
+        if (collection.accountName === $scope.accountName) {
           $scope.collectionList.push(collection);
         }
public/js/publish/publish-session.js (1)

326-339: Update PublishSession.resume to match the constructor refactor.

resume still calls new PublishSession($http, sessionData, accountData), so $interval ends up as the stored session blob and VersionHandler later tries to invoke it, throwing TypeError: sessionData is not a function. At the same time the real accounts/api keys are never passed in. Please realign the signature and pass the actual services you inject at bootstrap.

-    var publishSession = new PublishSession($http, sessionData, accountData);
+    var publishSession = new PublishSession($http, $interval, accounts, apiKeys);
+    Object.assign(publishSession, sessionData);
🧹 Nitpick comments (27)
public/templates/404.ejs (1)

3-3: Consider moving inline style to a CSS class.

The inline height: initial; style overrides the is-medium-small class. For better maintainability, consider creating a dedicated CSS class or modifier (e.g., is-medium-small-initial) rather than using inline styles.

devenv/random-downloader.sh (1)

1-8: Consider using established load-testing tools instead.

For development and testing purposes, established tools like siege, ab (Apache Bench), or wrk provide better control, metrics, and safety features. If this script is meant for CI/CD or performance testing, consider using a proper load-testing framework.

model/version.php (1)

269-275: Tighten the wasDerivedFrom validation message.

Line 273’s text reads “Value of prov:wasDerivedFrom from must be a valid IRI.” The duplicated “from” is distracting; consider smoothing the sentence for clarity.

Apply this diff to clean it up:

-	sh:message "Value of prov:wasDerivedFrom from must be a valid IRI."@en ;
+	sh:message "Value of prov:wasDerivedFrom must be a valid IRI."@en ;
public/css/_sparql.scss (1)

2-5: Consider whether !important is necessary.

The !important modifiers can make styles harder to maintain and debug. If these are overriding third-party Yasqe library styles, they may be necessary; otherwise, consider increasing specificity instead.

public/js/components/entity-dropdown/entity-dropdown.js (1)

69-69: Remove commented code.

The commented line // ctrl.onSelect(null); should either be implemented if needed or removed to keep the code clean.

Apply this diff if the line is not needed:

-      // ctrl.onSelect(null);
public/js/collections/databus-collection-manager.js (2)

477-481: Safe but consider extracting to filter operation.

Deleting entries during object iteration is safe in JavaScript, but for clarity, consider filtering the collection before serialization.

Optionally, refactor to a more declarative approach:

-    for (let identifier in this.local) {
-      if (this.local[identifier].accountName == null) {
-        delete (this.local[identifier]);
-      }
-    }
-
+    // Filter out collections without accountName before saving
+    const validCollections = Object.fromEntries(
+      Object.entries(this.local).filter(([_, col]) => col.accountName != null)
+    );
+
     try {
       //write local collections to local storage
-      window.localStorage.setItem(this.storageKey, DatabusCollectionUtils.serialize(this.local));
+      window.localStorage.setItem(this.storageKey, DatabusCollectionUtils.serialize(validCollections));

191-193: Consider: Use Error objects instead of string throws.

Multiple methods throw string messages. While functional, throwing Error objects provides better stack traces and is more conventional.

Example refactor:

-    if (!this.hasAccountName) throw "Databus-Collection-Manager is not initialized.";
+    if (!this.hasAccountName) throw new Error("Databus-Collection-Manager is not initialized.");

Also applies to: 293-293, 344-344, 413-413, 466-466, 520-520, 564-564, 583-583, 596-596, 650-650, 786-786, 811-811, 843-843

public/css/_fonts.scss (1)

1-47: Consider consistent quote style and remove trailing blank lines.

The font-face declarations are correct, but there are minor style inconsistencies:

  • Mixed single and double quotes in font-family and src declarations
  • Lines 40-42 contain unnecessary blank lines

For consistency, consider using either single or double quotes throughout, and remove the trailing blank lines.

public/js/page-controller/frontpage-controller.js (1)

57-68: Consider consolidating navigation logic or using a routing service.

The three navigation helpers (login, goToPage, account) all use window.location for full page reloads. While functional, you could consider:

  1. Consolidating these into a single navigation helper service to reduce duplication
  2. Using AngularJS routing (e.g., $location service) if available, for smoother client-side navigation

Example consolidation:

$scope.navigate = function(path, queryParams) {
  var url = path;
  if (queryParams) {
    url += '?' + new URLSearchParams(queryParams).toString();
  }
  window.location = url;
}

$scope.login = function() {
  $scope.navigate('/app/login', { redirectUrl: window.location.href });
}
public/templates/variables.ejs (1)

6-7: Add missing semicolons for consistency.

Lines 6 and 7 are missing semicolons while other statements have them.

-  var DATABUS_CONTEXT_URL = "<%= databus.contextUrl %>"
-  var DATABUS_NAME = "<%= databus.name %>";
+  var DATABUS_CONTEXT_URL = "<%= databus.contextUrl %>";
+  var DATABUS_NAME = "<%= databus.name %>";
public/templates/sparql-editor.ejs (1)

3-6: Remove empty style block or add a TODO comment.

The empty <style> block serves no purpose and should either be removed or documented if it's a placeholder for future styling.

-  <style>
-    
-
-  </style>
-

Or if this is intentional for future use:

   <style>
-    
-
+    /* TODO: Add SPARQL editor specific styles */
   </style>
deployment/.env (1)

2-10: Consider .env formatting best practices.

While functional, the file has several formatting inconsistencies flagged by static analysis tools. These are minor but worth addressing for consistency.

Key issues:

  • Line 2: Remove quotes around DATA_PATH value (or apply consistently)
  • Lines 6-7: Quote values containing spaces
  • Lines 9-10: Remove spaces around = sign

Example fixes:

-DATA_PATH="../../databus-data"
+DATA_PATH=../../databus-data
-DATABUS_NAME=My Local Databus
-DATABUS_ABSTRACT=A local instance for development
+DATABUS_NAME="My Local Databus"
+DATABUS_ABSTRACT="A local instance for development"
-DATABUS_BANNER_COLOR= # Default is #81b8b2
-DATABUS_TITLE_COLOR= # Default is white
+DATABUS_BANNER_COLOR="" # Default is #81b8b2
+DATABUS_TITLE_COLOR="" # Default is white
public/js/components/error-notification/error-notifcation.js (1)

11-13: Missing semicolon after return statement.

Line 12 is missing a semicolon, though this doesn't affect functionality due to automatic semicolon insertion.

Apply this diff for consistency:

   ctrl.get = function(key) {
-    return DatabusMsg.get(key);
+    return DatabusMsg.get(key);
   }

Note: Verify your project's semicolon convention and apply consistently across the codebase.

public/templates/publish-wizard copy.ejs (2)

8-101: Consider externalizing inline styles.

The large inline style block (94 lines) should be moved to an external CSS/SCSS file for better maintainability and reusability across templates.

Create a dedicated stylesheet:

  • Extract styles to public/css/_publish-wizard.scss
  • Import in your main SCSS file
  • Remove the <style> block from the template

This improves:

  • Code organization
  • Style reusability
  • Separation of concerns
  • Caching (external CSS can be cached by browsers)

243-243: TODO comments indicate incomplete implementation.

Multiple TODO comments suggest this template is not production-ready:

  • Line 243: Missing group list & create input
  • Line 310: Missing version input, file uploader, metadata fields

These incomplete sections indicate the wizard is not fully functional. Should this be:

  1. Marked as a work-in-progress/draft?
  2. Completed before merging to master?
  3. Tracked with GitHub issues?

Would you like me to open issues to track the remaining implementation work?

Also applies to: 310-310

public/js/page-controller/account-controller.js (1)

10-17: JSDoc parameter type annotation incomplete.

The JSDoc comment references DatabusCollectionManager but the actual parameters accounts and apiKeys are not documented. Consider completing the documentation or removing it if not maintained.

public/templates/user-settings.ejs (1)

6-65: Consider moving inline styles to external stylesheet.

The template contains approximately 60 lines of inline <style> tags. For maintainability and reusability, these styles should be moved to an external SCSS file (e.g., _user-settings.scss).

public/js/components/entity-api-view/entity-api-view.html (1)

4-10: Empty href attributes in tabs.

Lines 5 and 8 use href="", which will navigate to the current page if clicked before the ng-click handler fires. Use href="javascript:void(0)" or ng-href to prevent default navigation.

       <li ng-class="{ 'is-active': $ctrl.entity.sendmode === 'register' }">
-        <a href="" ng-click="$ctrl.entity.setSendMode('register')">Register</a>
+        <a href="javascript:void(0)" ng-click="$ctrl.entity.setSendMode('register')">Register</a>
       </li>
       <li ng-class="{ 'is-active': $ctrl.entity.sendmode === 'curl' }">
-        <a href="" ng-click="$ctrl.entity.setSendMode('curl')">cURL</a>
+        <a href="javascript:void(0)" ng-click="$ctrl.entity.setSendMode('curl')">cURL</a>
       </li>
public/css/_nav.scss (2)

7-17: Very high z-index value.

Line 8 sets z-index: 8000, which is extremely high and could cause stacking context issues with modals, tooltips, or other overlays. Typical navigation bars use values in the range of 100-1000.

Consider using a lower, more conventional z-index value (e.g., 1000) unless there's a specific requirement for such a high value. If other components require specific stacking orders, document the z-index scale in a comment or CSS variable.

// Z-index scale: nav=1000, dropdown=1001, modal=2000, tooltip=3000
z-index: 1000;

145-301: Complex nested selectors in search component.

The .nav-search section spans 150+ lines with deeply nested selectors (some nesting 4-5 levels deep). This increases specificity and makes the styles harder to override or maintain.

Consider flattening some of the nesting using BEM methodology or utility classes. For example:

// Instead of: .nav-search .results .result-item .item-header
.nav-search__result-item-header { ... }
docker-compose-4-swarm.yml (1)

2-64: Consider adding resource limits and health checks.

The services lack resource constraints (CPU/memory limits) and health checks. For a production swarm deployment, these are important for:

  1. Preventing resource exhaustion
  2. Enabling proper load balancing
  3. Facilitating automatic recovery

Add resource limits and health checks for each service:

  databus_virtuoso:
    # ... existing config ...
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 4G
        reservations:
          cpus: '1.0'
          memory: 2G
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8890/sparql"]
      interval: 30s
      timeout: 10s
      retries: 3
public/css/website.css (6)

2-2: Avoid CSS @import to node_modules at runtime

Prefer bundling or a to a built asset; @import adds render‑blocking and can 404 outside dev.
Example:

-@import '../node_modules/codemirror/lib/codemirror.css';

Load via your build pipeline (copy to /public and it), or inline into your main bundle.


23-40: Improve @font-face performance and compatibility

Add font-display and modern formats; include local() fallbacks.

 @font-face {
-  font-family: "Roboto";
-  src: url("./../fonts/Roboto-Regular.ttf");
+  font-family: "Roboto";
+  src: local("Roboto Regular"), local("Roboto-Regular"),
+       url("../fonts/roboto-regular.woff2") format("woff2"),
+       url("../fonts/Roboto-Regular.ttf") format("truetype");
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
 }
 @font-face {
-  font-family: "Roboto";
-  src: url("./../fonts/Roboto-Bold.ttf");
-  font-weight: bold;
+  font-family: "Roboto";
+  src: local("Roboto Bold"), local("Roboto-Bold"),
+       url("../fonts/roboto-bold.woff2") format("woff2"),
+       url("../fonts/Roboto-Bold.ttf") format("truetype");
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
 }
 @font-face {
   font-family: "Inter";
-  src: url("./../fonts/Inter-Regular.ttf");
+  src: local("Inter Regular"), local("Inter-Regular"),
+       url("../fonts/inter-regular.woff2") format("woff2"),
+       url("../fonts/Inter-Regular.ttf") format("truetype");
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
 }
 @font-face {
   font-family: "Inter";
-  src: url("./../fonts/Inter-SemiBold.ttf");
-  font-weight: 600;
+  src: local("Inter SemiBold"), local("Inter-SemiBold"),
+       url("../fonts/inter-semibold.woff2") format("woff2"),
+       url("../fonts/Inter-SemiBold.ttf") format("truetype");
+  font-style: normal;
+  font-weight: 600;
+  font-display: swap;
 }
```<!-- review_comment_end -->

---

`11948-11954`: **Redundant float with absolute positioning**

.version-tag uses float:right and position:absolute; float is unnecessary. 
```diff
 .version-tag {
-  color: white;
-  float: right;
-  position: absolute;
+  color: white;
+  position: absolute;
   padding: 0.5em;
   right: 0;
 }
```<!-- review_comment_end -->

---

`9964-9970`: **Duplicate “fill” utilities**

.fill and .fill-parent both absolutely fill the parent; keep one to avoid confusion. 
```diff
-.fill { position: absolute; top:0; bottom:0; right:0; left:0; }
-.fill-parent { position: absolute; top:0; right:0; bottom:0; left:0; }
+/* Keep one canonical utility */
+.fill { position: absolute; inset: 0; }
+/* Remove .fill-parent or alias it */
+.fill-parent { position: absolute; inset: 0; } /* optional alias */
```<!-- review_comment_end -->


Also applies to: 11919-11925

---

`12268-12273`: **Respect reduced motion preferences for rotations/transitions**

Add a prefers-reduced-motion guard to disable animations for users who opt out. 
Add near the end of the file:
```css
@media (prefers-reduced-motion: reduce) {
  .frontpage-box,
  .frontpage-box:hover,
  .expand-arrow,
  .expand-arrow.rotated {
    transition: none !important;
    transform: none !important;
  }
}
```<!-- review_comment_end -->

---

`1108-1112`: **Consider central color tokens (CSS variables) instead of hard-coded decimals**

Numerous rgb()/rgba() values with decimals reduce maintainability. Migrate to CSS custom properties (already hinted by _colors.scss) for consistency. 
Example:
```css
:root {
  --db-shadow: rgba(10,10,10,0.1);
  --db-link: #3867d6;
}
/* Then */
.box { box-shadow: 0 2px 3px var(--db-shadow), 0 0 0 1px var(--db-shadow); }
a { color: var(--db-link); }
```<!-- review_comment_end -->
<!-- file_end -->


Also applies to: 1156-1170, 1713-1724, 4886-4991

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used**: CodeRabbit UI

**Review profile**: CHILL

**Plan**: Pro

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 22dbf26f482b825c806c4ecc128ca97c1267bbae and 0e8983f220c19a7afd9742d50a91aab9eb7541e1.

</details>

<details>
<summary>⛔ Files ignored due to path filters (16)</summary>

* `model/generated/context.json` is excluded by `!**/generated/**`
* `model/generated/shacl/version.shacl` is excluded by `!**/generated/**`
* `public/dist/main.js` is excluded by `!**/dist/**`
* `public/fonts/Inter-Black.ttf` is excluded by `!**/*.ttf`
* `public/fonts/Inter-Bold.ttf` is excluded by `!**/*.ttf`
* `public/fonts/Inter-ExtraBold.ttf` is excluded by `!**/*.ttf`
* `public/fonts/Inter-ExtraLight.ttf` is excluded by `!**/*.ttf`
* `public/fonts/Inter-Light.ttf` is excluded by `!**/*.ttf`
* `public/fonts/Inter-Medium.ttf` is excluded by `!**/*.ttf`
* `public/fonts/Inter-Regular.ttf` is excluded by `!**/*.ttf`
* `public/fonts/Inter-SemiBold.ttf` is excluded by `!**/*.ttf`
* `public/fonts/Inter-Thin.ttf` is excluded by `!**/*.ttf`
* `public/fonts/Roboto-Bold.ttf` is excluded by `!**/*.ttf`
* `public/fonts/Roboto-Regular.ttf` is excluded by `!**/*.ttf`
* `search/lookup-indexer.jar` is excluded by `!**/*.jar`
* `search/lookup-server.jar` is excluded by `!**/*.jar`

</details>

<details>
<summary>📒 Files selected for processing (107)</summary>

* `.dockerignore` (1 hunks)
* `.env` (1 hunks)
* `.vscode/launch.json` (1 hunks)
* `.vscode/settings.json` (1 hunks)
* `Dockerfile` (1 hunks)
* `backup.sh` (1 hunks)
* `deployment/.env` (1 hunks)
* `deployment/README.md` (1 hunks)
* `deployment/docker-compose.yml` (1 hunks)
* `devenv/Makefile` (4 hunks)
* `devenv/README.md` (1 hunks)
* `devenv/docker-compose.yml` (2 hunks)
* `devenv/grafana-promql.md` (1 hunks)
* `devenv/prometheus.yml` (1 hunks)
* `devenv/random-downloader.sh` (1 hunks)
* `docker-compose-4-swarm.yml` (1 hunks)
* `docker-compose.yml` (3 hunks)
* `model/account.php` (1 hunks)
* `model/artifact.php` (2 hunks)
* `model/finalize.php` (1 hunks)
* `model/group.php` (2 hunks)
* `model/version.php` (3 hunks)
* `public/css/_colors.scss` (2 hunks)
* `public/css/_components.scss` (4 hunks)
* `public/css/_entities.scss` (3 hunks)
* `public/css/_fonts.scss` (1 hunks)
* `public/css/_frontpage.scss` (1 hunks)
* `public/css/_nav.scss` (1 hunks)
* `public/css/_sparql.scss` (1 hunks)
* `public/css/website.css` (153 hunks)
* `public/css/website.scss` (6 hunks)
* `public/js/angular-application.js` (7 hunks)
* `public/js/collections/databus-collection-manager.js` (22 hunks)
* `public/js/collections/databus-collection-wrapper.js` (1 hunks)
* `public/js/components/collection-hierarchy-two/collection-hierarchy.html` (2 hunks)
* `public/js/components/collection-hierarchy-two/collection-hierarchy.js` (2 hunks)
* `public/js/components/collection-search/collection-search.html` (1 hunks)
* `public/js/components/collection-search/collection-search.js` (2 hunks)
* `public/js/components/databus-icon/databus-icon.html` (1 hunks)
* `public/js/components/databus-icon/databus-icon.js` (2 hunks)
* `public/js/components/entity-api-view/entity-api-view.html` (1 hunks)
* `public/js/components/entity-api-view/entity-api-view.js` (1 hunks)
* `public/js/components/entity-card/entity-card.html` (2 hunks)
* `public/js/components/entity-dropdown/entity-dropdown.html` (1 hunks)
* `public/js/components/entity-dropdown/entity-dropdown.js` (1 hunks)
* `public/js/components/error-notification/error-notifcation.js` (1 hunks)
* `public/js/components/error-notification/error-notification.html` (1 hunks)
* `public/js/components/facets-view/facets-view.js` (9 hunks)
* `public/js/components/file-browser/file-browser.html` (1 hunks)
* `public/js/components/nav-search/nav-search-controller.js` (1 hunks)
* `public/js/components/nav-search/nav-search.html` (1 hunks)
* `public/js/components/search/search-controller.js` (1 hunks)
* `public/js/components/search/search.html` (1 hunks)
* `public/js/components/table-editor/table-editor.html` (3 hunks)
* `public/js/components/table-editor/table-editor.js` (6 hunks)
* `public/js/components/type-tag/type-tag.js` (2 hunks)
* `public/js/page-controller/account-controller.js` (11 hunks)
* `public/js/page-controller/artifact-controller.js` (3 hunks)
* `public/js/page-controller/collection-controller.js` (4 hunks)
* `public/js/page-controller/collections-editor-controller.js` (2 hunks)
* `public/js/page-controller/frontpage-controller.js` (1 hunks)
* `public/js/page-controller/group-controller.js` (7 hunks)
* `public/js/page-controller/header-controller.js` (1 hunks)
* `public/js/page-controller/profile-controller.js` (10 hunks)
* `public/js/page-controller/publish-wizard-controller.js` (6 hunks)
* `public/js/page-controller/sparql-editor-controller.js` (5 hunks)
* `public/js/page-controller/user-settings-controller.js` (1 hunks)
* `public/js/page-controller/version-controller.js` (6 hunks)
* `public/js/publish/artifact-data.js` (1 hunks)
* `public/js/publish/databus-sparql-client.js` (1 hunks)
* `public/js/publish/entity-handler.js` (1 hunks)
* `public/js/publish/group-data.js` (1 hunks)
* `public/js/publish/publish-data.js` (5 hunks)
* `public/js/publish/publish-session.js` (10 hunks)
* `public/js/publish/version-handler.js` (1 hunks)
* `public/js/search/search-manager.js` (2 hunks)
* `public/js/utils/app-json-formatter.js` (4 hunks)
* `public/js/utils/databus-messages.js` (1 hunks)
* `public/js/utils/databus-uris.js` (2 hunks)
* `public/js/utils/databus-utils.js` (7 hunks)
* `public/js/utils/databus-webapp-utils.js` (1 hunks)
* `public/js/utils/jsonld-utils.js` (4 hunks)
* `public/js/utils/messages.js` (1 hunks)
* `public/js/utils/tab-navigation.js` (2 hunks)
* `public/templates/404.ejs` (1 hunks)
* `public/templates/account.ejs` (7 hunks)
* `public/templates/artifact.ejs` (1 hunks)
* `public/templates/banner.ejs` (1 hunks)
* `public/templates/collection-editor.ejs` (1 hunks)
* `public/templates/collections-editor.ejs` (1 hunks)
* `public/templates/download.ejs` (0 hunks)
* `public/templates/group.ejs` (0 hunks)
* `public/templates/header.ejs` (2 hunks)
* `public/templates/index.ejs` (2 hunks)
* `public/templates/nav.ejs` (1 hunks)
* `public/templates/profile.ejs` (5 hunks)
* `public/templates/publish-wizard copy.ejs` (1 hunks)
* `public/templates/publish-wizard-old.ejs` (1 hunks)
* `public/templates/publish-wizard.ejs` (1 hunks)
* `public/templates/sparql-editor.ejs` (3 hunks)
* `public/templates/unauthorized.ejs` (3 hunks)
* `public/templates/user-settings.ejs` (1 hunks)
* `public/templates/variables.ejs` (1 hunks)
* `search/Dockerfile` (0 hunks)
* `search/docker-compose.yml` (0 hunks)
* `search/gstore-helper.js` (0 hunks)
* `search/index-config.yml` (2 hunks)

</details>

<details>
<summary>⛔ Files not processed due to max files limit (57)</summary>

* search/indexer/account.yml
* search/indexer/artifact.yml
* search/indexer/collection.yml
* search/indexer/group.yml
* search/indexer/version.yml
* search/servlet-config.yml
* server/app/api/lib/account-writer.js
* server/app/api/lib/artifact-writer.js
* server/app/api/lib/collection-writer.js
* server/app/api/lib/databus-tractate-suite.js
* server/app/api/lib/dataid-autocomplete.js
* server/app/api/lib/group-writer.js
* server/app/api/lib/gstore-resource.js
* server/app/api/lib/publish-account.js
* server/app/api/lib/publish-artifact.js
* server/app/api/lib/publish-group.js
* server/app/api/lib/publish-version.js
* server/app/api/lib/resource-writer.js
* server/app/api/module.js
* server/app/api/routes/account.js
* server/app/api/routes/artifact.js
* server/app/api/routes/collection.js
* server/app/api/routes/general.js
* server/app/api/routes/group.js
* server/app/api/routes/version.js
* server/app/api/statistics/metrics-manager.js
* server/app/api/swagger-client.js
* server/app/api/swagger-page.js
* server/app/api/swagger.yml
* server/app/api/webdav.js
* server/app/app.js
* server/app/common/404.js
* server/app/common/constants.js
* server/app/common/databus-logger.js
* server/app/common/databus-message.js
* server/app/common/databus-resource.js
* server/app/common/execute-construct.js
* server/app/common/execute-query.js
* server/app/common/get-jsonld.js
* server/app/common/get-linked-data.js
* server/app/common/protect/middleware.js
* server/app/common/queries/constructs/ld/construct-artifact.sparql
* server/app/common/queries/constructs/ld/construct-group.sparql
* server/app/common/queries/query-modules/accounts.js
* server/app/common/queries/query-modules/collections.js
* server/app/common/queries/query-modules/pages.js
* server/app/common/queries/sparql/get-artifacts-by-account.sparql
* server/app/common/queries/sparql/get-collection-content.sparql
* server/app/common/queries/sparql/get-collection.sparql
* server/app/common/queries/sparql/get-collections-by-account.sparql
* server/app/common/queries/sparql/get-groups-by-account.sparql
* server/app/common/queries/userdb/add-account.sql
* server/app/common/queries/userdb/add-api-key.sql
* server/app/common/queries/userdb/add-user.sql
* server/app/common/queries/userdb/create-account-table.sql
* server/app/common/queries/userdb/create-api-key-table.sql
* server/app/common/queries/userdb/create-user-table.sql

</details>

<details>
<summary>💤 Files with no reviewable changes (5)</summary>

* search/Dockerfile
* public/templates/group.ejs
* search/docker-compose.yml
* public/templates/download.ejs
* search/gstore-helper.js

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code graph analysis (23)</summary>

<details>
<summary>public/js/components/error-notification/error-notifcation.js (2)</summary><blockquote>

<details>
<summary>public/js/angular-application.js (1)</summary>

* `ErrorNotificationController` (42-42)

</details>
<details>
<summary>public/js/utils/messages.js (1)</summary>

* `DatabusMsg` (1-23)

</details>

</blockquote></details>
<details>
<summary>public/js/collections/databus-collection-wrapper.js (1)</summary><blockquote>

<details>
<summary>server/app/api/routes/account.js (3)</summary>

* `accountName` (110-110)
* `accountName` (167-167)
* `accountName` (219-219)

</details>

</blockquote></details>
<details>
<summary>public/js/page-controller/account-controller.js (1)</summary><blockquote>

<details>
<summary>public/js/collections/databus-collection-manager.js (1)</summary>

* `DatabusUtils` (3-3)

</details>

</blockquote></details>
<details>
<summary>public/js/components/collection-hierarchy-two/collection-hierarchy.js (1)</summary><blockquote>

<details>
<summary>public/js/components/collection-search/collection-search.js (4)</summary>

* `node` (52-52)
* `node` (68-68)
* `node` (85-85)
* `uri` (51-51)

</details>

</blockquote></details>
<details>
<summary>public/js/components/collection-search/collection-search.js (1)</summary><blockquote>

<details>
<summary>public/js/components/collection-hierarchy-two/collection-hierarchy.js (9)</summary>

* `uri` (298-298)
* `QueryNode` (3-3)
* `node` (124-124)
* `node` (167-167)
* `node` (175-175)
* `node` (183-183)
* `node` (197-197)
* `node` (213-213)
* `node` (299-299)

</details>

</blockquote></details>
<details>
<summary>public/js/components/entity-dropdown/entity-dropdown.js (1)</summary><blockquote>

<details>
<summary>public/js/angular-application.js (1)</summary>

* `EntityDropdownController` (40-40)

</details>

</blockquote></details>
<details>
<summary>public/js/utils/databus-utils.js (3)</summary><blockquote>

<details>
<summary>server/app/api/routes/general.js (1)</summary>

* `ApiError` (12-12)

</details>
<details>
<summary>server/app/api/lib/account-writer.js (1)</summary>

* `ApiError` (5-5)

</details>
<details>
<summary>server/app/api/lib/resource-writer.js (1)</summary>

* `ApiError` (4-4)

</details>

</blockquote></details>
<details>
<summary>public/js/components/entity-api-view/entity-api-view.js (1)</summary><blockquote>

<details>
<summary>public/js/angular-application.js (1)</summary>

* `EntityApiViewController` (41-41)

</details>

</blockquote></details>
<details>
<summary>public/js/publish/group-data.js (1)</summary><blockquote>

<details>
<summary>public/js/publish/entity-handler.js (2)</summary>

* `DatabusUtils` (2-2)
* `DatabusUris` (1-1)

</details>

</blockquote></details>
<details>
<summary>public/js/publish/databus-sparql-client.js (3)</summary><blockquote>

<details>
<summary>public/js/publish/entity-handler.js (1)</summary>

* `DatabusSparqlClient` (3-3)

</details>
<details>
<summary>public/js/publish/group-data.js (1)</summary>

* `DatabusSparqlClient` (4-4)

</details>
<details>
<summary>public/js/publish/publish-session.js (1)</summary>

* `DatabusSparqlClient` (7-7)

</details>

</blockquote></details>
<details>
<summary>public/js/page-controller/artifact-controller.js (4)</summary><blockquote>

<details>
<summary>public/js/page-controller/publish-wizard-controller.js (1)</summary>

* `DatabusWebappUtils` (1-1)

</details>
<details>
<summary>public/js/page-controller/group-controller.js (2)</summary>

* `DatabusWebappUtils` (9-9)
* `DataIdCreator` (3-3)

</details>
<details>
<summary>public/js/page-controller/version-controller.js (2)</summary>

* `DatabusWebappUtils` (1-1)
* `DataIdCreator` (8-8)

</details>
<details>
<summary>public/js/publish/publish-session.js (1)</summary>

* `DataIdCreator` (6-6)

</details>

</blockquote></details>
<details>
<summary>public/js/page-controller/user-settings-controller.js (3)</summary><blockquote>

<details>
<summary>public/js/page-controller/profile-controller.js (11)</summary>

* `DatabusAlert` (3-3)
* `index` (126-126)
* `account` (87-87)
* `account` (124-124)
* `account` (263-263)
* `account` (284-284)
* `response` (96-96)
* `response` (267-267)
* `message` (115-115)
* `message` (146-146)
* `postData` (89-92)

</details>
<details>
<summary>server/app/api/routes/account.js (4)</summary>

* `secretaryGraph` (74-74)
* `accountName` (110-110)
* `accountName` (167-167)
* `accountName` (219-219)

</details>
<details>
<summary>public/js/angular-application.js (1)</summary>

* `UserSettingsController` (11-11)

</details>

</blockquote></details>
<details>
<summary>public/js/page-controller/group-controller.js (3)</summary><blockquote>

<details>
<summary>server/app/api/lib/dataid-autocomplete.js (2)</summary>

* `DatabusConstants` (9-9)
* `require` (7-7)

</details>
<details>
<summary>public/js/page-controller/profile-controller.js (4)</summary>

* `DatabusConstants` (6-6)
* `DatabusWebappUtils` (2-2)
* `response` (96-96)
* `response` (267-267)

</details>
<details>
<summary>public/js/utils/app-json-formatter.js (1)</summary>

* `DatabusConstants` (1-1)

</details>

</blockquote></details>
<details>
<summary>public/js/components/nav-search/nav-search-controller.js (1)</summary><blockquote>

<details>
<summary>public/js/angular-application.js (1)</summary>

* `NavSearchController` (39-39)

</details>

</blockquote></details>
<details>
<summary>public/js/publish/publish-session.js (5)</summary><blockquote>

<details>
<summary>public/js/publish/entity-handler.js (3)</summary>

* `DatabusSparqlClient` (3-3)
* `DatabusUris` (1-1)
* `DatabusUtils` (2-2)

</details>
<details>
<summary>public/js/publish/group-data.js (3)</summary>

* `DatabusSparqlClient` (4-4)
* `DatabusUris` (3-3)
* `DatabusUtils` (2-2)

</details>
<details>
<summary>public/js/page-controller/publish-wizard-controller.js (1)</summary>

* `accounts` (43-43)

</details>
<details>
<summary>public/js/publish/version-handler.js (2)</summary>

* `DatabusUris` (3-3)
* `DatabusUtils` (2-2)

</details>
<details>
<summary>public/js/publish/artifact-data.js (2)</summary>

* `DatabusUris` (3-3)
* `DatabusUtils` (2-2)

</details>

</blockquote></details>
<details>
<summary>public/js/utils/databus-webapp-utils.js (2)</summary><blockquote>

<details>
<summary>server/app/api/routes/account.js (3)</summary>

* `accountName` (110-110)
* `accountName` (167-167)
* `accountName` (219-219)

</details>
<details>
<summary>public/js/page-controller/profile-controller.js (4)</summary>

* `account` (87-87)
* `account` (124-124)
* `account` (263-263)
* `account` (284-284)

</details>

</blockquote></details>
<details>
<summary>public/js/publish/publish-data.js (1)</summary><blockquote>

<details>
<summary>server/app/common/queries/query-modules/dataid.js (1)</summary>

* `versionUri` (323-323)

</details>

</blockquote></details>
<details>
<summary>public/js/publish/artifact-data.js (3)</summary><blockquote>

<details>
<summary>public/js/publish/version-handler.js (4)</summary>

* `EntityHandler` (1-1)
* `DatabusUtils` (2-2)
* `DatabusUris` (3-3)
* `GroupData` (4-4)

</details>
<details>
<summary>public/js/publish/group-data.js (3)</summary>

* `EntityHandler` (1-1)
* `DatabusUtils` (2-2)
* `DatabusUris` (3-3)

</details>
<details>
<summary>public/js/publish/entity-handler.js (2)</summary>

* `DatabusUtils` (2-2)
* `DatabusUris` (1-1)

</details>

</blockquote></details>
<details>
<summary>public/js/angular-application.js (2)</summary><blockquote>

<details>
<summary>public/js/components/error-notification/error-notifcation.js (1)</summary>

* `require` (1-1)

</details>
<details>
<summary>public/js/utils/databus-facets-cache.js (1)</summary>

* `require` (1-1)

</details>

</blockquote></details>
<details>
<summary>public/js/collections/databus-collection-manager.js (5)</summary><blockquote>

<details>
<summary>public/js/page-controller/profile-controller.js (1)</summary>

* `AppJsonFormatter` (7-7)

</details>
<details>
<summary>server/app/webapp/modules/resource-pages.js (2)</summary>

* `AppJsonFormatter` (18-18)
* `require` (10-10)

</details>
<details>
<summary>server/validate.js (2)</summary>

* `AppJsonFormatter` (7-7)
* `require` (6-6)

</details>
<details>
<summary>public/js/page-controller/version-controller.js (1)</summary>

* `AppJsonFormatter` (12-12)

</details>
<details>
<summary>public/js/search/search-manager.js (1)</summary>

* `AppJsonFormatter` (1-1)

</details>

</blockquote></details>
<details>
<summary>public/js/page-controller/publish-wizard-controller.js (9)</summary><blockquote>

<details>
<summary>public/js/page-controller/account-controller.js (1)</summary>

* `TabNavigation` (4-4)

</details>
<details>
<summary>public/js/page-controller/user-settings-controller.js (1)</summary>

* `TabNavigation` (5-5)

</details>
<details>
<summary>public/js/page-controller/collections-editor-controller.js (1)</summary>

* `TabNavigation` (9-9)

</details>
<details>
<summary>public/js/page-controller/artifact-controller.js (1)</summary>

* `TabNavigation` (9-9)

</details>
<details>
<summary>public/js/page-controller/group-controller.js (1)</summary>

* `TabNavigation` (10-10)

</details>
<details>
<summary>public/js/page-controller/version-controller.js (1)</summary>

* `TabNavigation` (6-6)

</details>
<details>
<summary>server/app/webapp/modules/resource-pages.js (2)</summary>

* `require` (10-10)
* `accounts` (49-49)

</details>
<details>
<summary>server/app/webapp/modules/account-page.js (2)</summary>

* `require` (6-6)
* `accounts` (27-27)

</details>
<details>
<summary>public/js/angular-application.js (1)</summary>

* `PublishWizardController` (9-9)

</details>

</blockquote></details>
<details>
<summary>public/js/page-controller/collections-editor-controller.js (3)</summary><blockquote>

<details>
<summary>public/js/page-controller/publish-wizard-controller.js (1)</summary>

* `DatabusWebappUtils` (1-1)

</details>
<details>
<summary>public/js/page-controller/account-controller.js (1)</summary>

* `DatabusWebappUtils` (3-3)

</details>
<details>
<summary>public/js/page-controller/collection-controller.js (1)</summary>

* `DatabusWebappUtils` (5-5)

</details>

</blockquote></details>
<details>
<summary>public/js/page-controller/profile-controller.js (3)</summary><blockquote>

<details>
<summary>server/app/api/swagger-page.js (2)</summary>

* `data` (28-28)
* `index` (44-44)

</details>
<details>
<summary>server/app/api/routes/account.js (6)</summary>

* `accountName` (110-110)
* `accountName` (167-167)
* `accountName` (219-219)
* `accountUri` (135-135)
* `accountUri` (187-187)
* `accountUri` (239-239)

</details>
<details>
<summary>public/js/page-controller/user-settings-controller.js (7)</summary>

* `postData` (175-178)
* `response` (182-182)
* `message` (147-147)
* `message` (201-201)
* `message` (230-230)
* `index` (128-128)
* `index` (210-210)

</details>

</blockquote></details>

</details><details>
<summary>🪛 Biome (2.1.2)</summary>

<details>
<summary>public/js/components/facets-view/facets-view.js</summary>

[error] 146-146: This variable is used before its declaration.

The variable is declared here:


(lint/correctness/noInvalidUseBeforeDeclaration)

---

[error] 255-255: Shouldn't redeclare 'artifactFacetData'. Consider to delete it or rename it.

'artifactFacetData' is defined here:


(lint/suspicious/noRedeclare)

---

[error] 260-260: Shouldn't redeclare 'i'. Consider to delete it or rename it.

'i' is defined here:


(lint/suspicious/noRedeclare)

---

[error] 298-298: Shouldn't redeclare 'setting'. Consider to delete it or rename it.

'setting' is defined here:


(lint/suspicious/noRedeclare)

---

[error] 322-322: Shouldn't redeclare 'artifactUri'. Consider to delete it or rename it.

'artifactUri' is defined here:


(lint/suspicious/noRedeclare)

---

[error] 324-324: Shouldn't redeclare 'artifactNode'. Consider to delete it or rename it.

'artifactNode' is defined here:


(lint/suspicious/noRedeclare)

</details>
<details>
<summary>public/js/components/nav-search/nav-search-controller.js</summary>

[error] 65-65: Shouldn't redeclare 'resourceType'. Consider to delete it or rename it.

'resourceType' is defined here:


(lint/suspicious/noRedeclare)

</details>
<details>
<summary>public/js/page-controller/version-controller.js</summary>

[error] 141-141: Shouldn't redeclare 'response'. Consider to delete it or rename it.

'response' is defined here:


(lint/suspicious/noRedeclare)

</details>
<details>
<summary>public/js/utils/app-json-formatter.js</summary>

[error] 12-12: Shouldn't redeclare 'name'. Consider to delete it or rename it.

'name' is defined here:


(lint/suspicious/noRedeclare)

</details>
<details>
<summary>public/js/publish/version-handler.js</summary>

[error] 262-262: Shouldn't redeclare 'c'. Consider to delete it or rename it.

'c' is defined here:


(lint/suspicious/noRedeclare)

---

[error] 263-263: Shouldn't redeclare 'cv'. Consider to delete it or rename it.

'cv' is defined here:


(lint/suspicious/noRedeclare)

---

[error] 269-269: Shouldn't redeclare 'value'. Consider to delete it or rename it.

'value' is defined here:


(lint/suspicious/noRedeclare)

</details>
<details>
<summary>public/js/publish/entity-handler.js</summary>

[error] 97-104: Duplicate class member name "setAccountName"



(lint/suspicious/noDuplicateClassMembers)

</details>
<details>
<summary>public/css/website.css</summary>

[error] 10869-10869: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

-webkit-transform is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

</details>

</details>
<details>
<summary>🪛 dotenv-linter (4.0.0)</summary>

<details>
<summary>deployment/.env</summary>

[warning] 2-2: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)

---

[warning] 4-4: [UnorderedKey] The DATABUS_RESOURCE_BASE_URL key should go before the DATA_PATH key

(UnorderedKey)

---

[warning] 6-6: [UnorderedKey] The DATABUS_NAME key should go before the DATABUS_RESOURCE_BASE_URL key

(UnorderedKey)

---

[warning] 6-6: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)

---

[warning] 7-7: [UnorderedKey] The DATABUS_ABSTRACT key should go before the DATABUS_NAME key

(UnorderedKey)

---

[warning] 7-7: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)

---

[warning] 8-8: [UnorderedKey] The DATABUS_ORG_ICON key should go before the DATABUS_RESOURCE_BASE_URL key

(UnorderedKey)

---

[warning] 9-9: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)

---

[warning] 9-9: [UnorderedKey] The DATABUS_BANNER_COLOR key should go before the DATABUS_NAME key

(UnorderedKey)

---

[warning] 9-9: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)

---

[warning] 10-10: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)

---

[warning] 10-10: [UnorderedKey] The DATABUS_TITLE_COLOR key should go before the DATA_PATH key

(UnorderedKey)

---

[warning] 10-10: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)

---

[warning] 12-12: [UnorderedKey] The DATABUS_OIDC_ISSUER_BASE_URL key should go before the DATABUS_ORG_ICON key

(UnorderedKey)

---

[warning] 13-13: [UnorderedKey] The DATABUS_OIDC_CLIENT_ID key should go before the DATABUS_OIDC_ISSUER_BASE_URL key

(UnorderedKey)

---

[warning] 14-14: [UnorderedKey] The DATABUS_OIDC_SECRET key should go before the DATABUS_ORG_ICON key

(UnorderedKey)

---

[warning] 15-15: [UnorderedKey] The DATABUS_PRIVATE_MODE key should go before the DATABUS_RESOURCE_BASE_URL key

(UnorderedKey)

---

[warning] 19-19: [UnorderedKey] The VIRTUOSO_PASSWORD key should go before the VIRTUOSO_USER key

(UnorderedKey)

</details>
<details>
<summary>.env</summary>

[warning] 6-6: [UnorderedKey] The DATABUS_ABSTRACT key should go before the DATABUS_NAME key

(UnorderedKey)

---

[warning] 6-6: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)

</details>

</details>
<details>
<summary>🪛 Gitleaks (8.28.0)</summary>

<details>
<summary>deployment/.env</summary>

[high] 14-14: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>
<details>
<summary>.vscode/launch.json</summary>

[high] 23-23: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

---

[high] 48-48: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

---

[high] 75-75: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>
<details>
<summary>🪛 LanguageTool</summary>

<details>
<summary>devenv/README.md</summary>

[grammar] ~6-~6: Ensure spelling is correct
Context: ...erver is providing both the API and the webapp resources. The webapp does not have its...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

</details>

</details>
<details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>

<details>
<summary>deployment/README.md</summary>

8-8: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>
<details>
<summary>🪛 Shellcheck (0.11.0)</summary>

<details>
<summary>devenv/random-downloader.sh</summary>

[warning] 7-7: Quote this to prevent word splitting.

(SC2046)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

<details>
<summary>devenv/prometheus.yml</summary>

[error] 1-1: wrong new line character: expected \n

(new-lines)

</details>

</details>

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

"DATABUS_OIDC_ISSUER_BASE_URL": "https://kilt.eu.auth0.com",
"DATABUS_OIDC_CLIENT_ID": "e9eOLS9IkGvuyBl7cBorWUQTNgbqejhc",
"DATABUS_OIDC_REQUIRED_ROLE": "",
"DATABUS_OIDC_SECRET": "0RVo9jMnbhPnkR6Ttz0aXQRTcRuSz5DpqyUEjbbcbgRuGA4rbwCjnHM2cOlTrv9q",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Remove hardcoded secrets from version control.

The launch.json file contains hardcoded OIDC secrets that should not be committed to version control. These secrets provide authentication access and could be misused if exposed.

Replace hardcoded secrets with references to environment variables or a local .env file:

-        "DATABUS_OIDC_SECRET": "0RVo9jMnbhPnkR6Ttz0aXQRTcRuSz5DpqyUEjbbcbgRuGA4rbwCjnHM2cOlTrv9q",
+        "DATABUS_OIDC_SECRET": "${env:DATABUS_OIDC_SECRET}",

Additionally, consider adding .vscode/launch.json to .gitignore and providing a .vscode/launch.json.example template instead.

Also applies to: 48-48, 75-75

🧰 Tools
🪛 Gitleaks (8.28.0)

[high] 23-23: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
.vscode/launch.json (lines 23, 48, 75): hardcoded OIDC secrets are committed;
remove the literal secret values and replace them with environment-variable
references (e.g. use an env lookup placeholder or load from process env at
runtime) so no secret appears in the file, add .vscode/launch.json to
.gitignore, and create a .vscode/launch.json.example template with placeholder
values and instructions for developers to populate their own local .env or IDE
environment variables; ensure any CI/local docs are updated to show how to set
DATABUS_OIDC_SECRET securely.

Comment on lines +15 to +18
localFolder="/devenv/data"

# Target folder on the remote server to copy the file into
targetFolder="/path/to/remote/folder"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Configure required paths before use.

  • Line 15: The path /devenv/data appears to be an absolute path starting from root, which is likely incorrect. Did you mean ./devenv/data (relative to script location)?
  • Line 18: The placeholder path /path/to/remote/folder must be updated with the actual remote destination.
🤖 Prompt for AI Agents
In backup.sh around lines 15 to 18, the configured paths are incorrect
placeholders: change localFolder from an absolute root path (/devenv/data) to
either a relative path (e.g., ./devenv/data) or make it configurable via
SCRIPT_DIR=$(dirname "$0") and reference "$SCRIPT_DIR/devenv/data"; replace
targetFolder "/path/to/remote/folder" with the actual remote destination
(user@host:/remote/path) or expose it as a required environment
variable/argument and validate it before proceeding. Ensure the script documents
or checks these variables and exits with an error if they remain unset or still
contain the placeholder text.

Comment on lines +21 to +33
docker compose stop

# Create a tar.gz archive of the local folder with the composed filename
tar -czf "$filename" "$localFolder"

# Securely copy the archive to the remote server's target folder
scp "$filename" "$targetFolder"

# Remove the local tar.gz archive to clean up
rm "$filename"

# Restart the databus, adjust for stack
docker compose up -d No newline at end of file
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add error handling and validation.

The script lacks error handling, which could lead to data loss or extended service downtime if any command fails. Consider adding:

+set -e  # Exit on any error
+set -u  # Exit on undefined variable
+
 # Shut down the databus, adjust for stack
 docker compose stop
+if [ $? -ne 0 ]; then
+  echo "Failed to stop docker services"
+  exit 1
+fi
 
 # Create a tar.gz archive of the local folder with the composed filename
 tar -czf "$filename" "$localFolder"
+if [ $? -ne 0 ]; then
+  echo "Failed to create backup archive"
+  docker compose up -d
+  exit 1
+fi
 
 # Securely copy the archive to the remote server's target folder
 scp "$filename" "$targetFolder"
+if [ $? -ne 0 ]; then
+  echo "Failed to copy backup to remote server"
+  rm "$filename"
+  docker compose up -d
+  exit 1
+fi
 
 # Remove the local tar.gz archive to clean up
 rm "$filename"
 
 # Restart the databus, adjust for stack
 docker compose up -d
+if [ $? -ne 0 ]; then
+  echo "Failed to restart docker services"
+  exit 1
+fi
+
+echo "Backup completed successfully"

Committable suggestion skipped: line range outside the PR's diff.

tar -czf "$filename" "$localFolder"

# Securely copy the archive to the remote server's target folder
scp "$filename" "$targetFolder"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix incomplete scp command.

The scp command is missing the remote host specification. It should be:

-scp "$filename" "$targetFolder"
+scp "$filename" user@host:"$targetFolder"

Replace user@host with the actual remote username and hostname.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In backup.sh around line 27, the scp invocation is incomplete because it lacks
the remote host target; update the command to include the remote user and host
(and optional remote path) in the destination, e.g. replace the current
"$targetFolder" with user@host:"$targetFolder" (substituting the actual username
and hostname for user@host), ensuring variables are quoted as needed and include
the colon to denote a remote path.

Comment on lines +12 to +14
DATABUS_OIDC_ISSUER_BASE_URL=https://kilt.eu.auth0.com
DATABUS_OIDC_CLIENT_ID=K5PCEOr7OJGBGU9xN7SvBrX1RWDs4S4n
DATABUS_OIDC_SECRET=LiL_X1tzwRmReU3RO7kBlBdDopmVEGf4gj5Ve8No16kifyi3weXK7u6IS1Ttpl_q
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Remove actual secrets from version control.

The OIDC secret appears to be a real credential committed to the repository. Even for development/testing, actual secrets should never be committed to version control.

Replace with placeholder values and document in README:

 # OIDC SETTINGS - Only use these values for testing and enter your own OIDC provider values
-DATABUS_OIDC_ISSUER_BASE_URL=https://kilt.eu.auth0.com
-DATABUS_OIDC_CLIENT_ID=K5PCEOr7OJGBGU9xN7SvBrX1RWDs4S4n
-DATABUS_OIDC_SECRET=LiL_X1tzwRmReU3RO7kBlBdDopmVEGf4gj5Ve8No16kifyi3weXK7u6IS1Ttpl_q
+DATABUS_OIDC_ISSUER_BASE_URL=https://your-issuer.example.com
+DATABUS_OIDC_CLIENT_ID=your-client-id-here
+DATABUS_OIDC_SECRET=your-client-secret-here

Consider:

  1. Rotating the exposed secret immediately
  2. Using .env.example for templates with placeholder values
  3. Ensuring .env is in .gitignore for production deployments

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 12-12: [UnorderedKey] The DATABUS_OIDC_ISSUER_BASE_URL key should go before the DATABUS_ORG_ICON key

(UnorderedKey)


[warning] 13-13: [UnorderedKey] The DATABUS_OIDC_CLIENT_ID key should go before the DATABUS_OIDC_ISSUER_BASE_URL key

(UnorderedKey)


[warning] 14-14: [UnorderedKey] The DATABUS_OIDC_SECRET key should go before the DATABUS_ORG_ICON key

(UnorderedKey)

🪛 Gitleaks (8.28.0)

[high] 14-14: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
In deployment/.env around lines 12 to 14 the OIDC client secret is a real
credential committed to the repo; remove the secret and replace the values with
non-sensitive placeholders (e.g. DATABUS_OIDC_CLIENT_ID=your-client-id,
DATABUS_OIDC_SECRET=your-client-secret), add a .env.example file with those
placeholders, ensure deployment/.env is listed in .gitignore, remove the
committed secret from history (git rm --cached deployment/.env and commit, then
rotate the exposed secret immediately in the identity provider), and document in
the README how to obtain and store the real secret securely for deployments.

Comment on lines +1 to +320
<%- include('header') -%>

<script src="/node_modules/stream-file/dist/stream-file.min.js"></script>
<script src="/node_modules/js-sha256/build/sha256.min.js"></script>

<div ng-controller="PublishWizardController" ng-cloak>

<style>
/* Wizard Container & Layout */
.wizard-container {
display: flex;
gap: 2rem;
}
/* Sidebar Navigation */
.wizard-sidebar {
width: 320px;
}
.wizard-step-tab {
background-color: #f9f9f9;
border: 1px solid #ddd;
border-radius: 6px;
padding: 0.75rem 1rem;
margin-bottom: 0.75rem;
cursor: pointer;
transition: background-color 0.2s ease;
}
.wizard-step-tab.is-valid {
background-color: #d3f0c8;
border: 1px solid #78c04c;
color: 1px solid #78c04c;
}
.wizard-step-tab.is-active.is-valid {
background-color: #b3ea9f;
border: 1px solid #529f23;
}
.wizard-step-tab.is-active {
background-color: #dbdbdb;
border-color: #bbb;
}
.wizard-step-tab .label {
font-size: 0.85rem;
color: #555;
margin-bottom: 0.25rem;
}
.wizard-step-tab .value {
font-size: 1rem;
color: #222;
}
/* Wizard Content Box */
.wizard-content {
flex: 1;
}
.box-content {
background: #fff;
border: 1px solid #ddd;
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
}
.row {
display: flex;
align-items: center;
margin-bottom: 1rem;
}
.row-label {
width: 160px;
font-weight: 500;
color: #444;
}
.dropdown-item:hover {
background-color: #f5f5f5;
}
/* Nerd Mode Toggle */
.nerd-toggle {
display: flex;
align-items: center;
justify-content: flex-end;
position: fixed;
top: 0.5rem;
right: 1rem;
z-index: 1000;
}
/* Typography & Spacing */
.mt-1 { margin-top: 0.75rem; }
.mb-1 { margin-bottom: 0.75rem; }
.mb-2 { margin-bottom: 1rem; }
</style>

<!-- Nerd Mode Toggle -->
<div class="nerd-toggle" ng-if="authenticated">
<div class="field override-checkbox" ng-class="{ 'is-override' : nerdMode.enabled }">
<input id="check--nerdMode" name="check--nerdMode" class="is-checkradio" type="checkbox"
ng-model="nerdMode.enabled">
<label for="check--nerdMode">
<span>Nerd Mode</span>
</label>
</div>
</div>

<!-- Wizard Layout -->
<div class="section">
<div class="container">
<div class="wizard-info content" style="padding-top: 0;">
<h1 class="title">Metadata Wizard</h1>
<p>The metadata wizard helps generate and publish Databus metadata step-by-step. Choose options below to create valid JSON-LD metadata.</p>
<p ng-if="nerdMode.enabled"><b>NERD MODE ENABLED</b> — Directly send raw JSON-LD to the API. You know what you're doing.</p>
</div>

<div class="wizard-container">

<!-- Sidebar Step Navigation -->
<div class="wizard-sidebar">
<div class="wizard-step-tab" ng-class="{
'is-valid' : session.accountData.isValid,
'is-active' : tabNavigation.activeTab == 0
}"
ng-click="tabNavigation.navigateTo('account');">
<div class="label">1. Account</div>
<div class="value">{{ session.accountData.name || 'Select' }}</div>
</div>
<div class="wizard-step-tab" ng-class="{
'is-valid' : session.formData.group.errors.length == 0,
'is-active' : tabNavigation.activeTab == 1
}"
ng-click="tabNavigation.navigateTo('group');">
<div class="label">2. Group</div>
<div class="value">{{ session.formData.group.name || 'Select or create' }}</div>
</div>
<div class="wizard-step-tab" ng-class="{
'is-active' : tabNavigation.activeTab == 2,
'is-valid' : session.formData.artifact.errors.length == 0
}"
ng-click="tabNavigation.navigateTo('artifact');">
<div class="label">3. Artifact</div>
<div class="value">{{ session.formData.artifact.name || 'Select or create' }}</div>
</div>
<div class="wizard-step-tab" ng-class="{ 'is-active' : tabNavigation.activeTab == 3 }"
ng-click="tabNavigation.navigateTo('version');">
<div class="label">4. Version</div>
<div class="value">{{ session.formData.version.version || 'Select or create' }}</div>
</div>
</div>

<!-- Main Content Panel -->
<div class="wizard-content">

<!-- Step 1: Account -->
<div ng-if="tabNavigation.activeTab == 0">
<h2 class="subtitle">Step 1: Choose Account</h2>
<div class="row">
<div class="row-label">Account Name</div>
<div style="flex: 1">
<div class="dropdown is-hoverable">
<div class="dropdown-trigger">
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu">
<span>{{ session.accountData.name }}</span>
<span class="icon is-small">
<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu" role="menu">
<div class="dropdown-content">
<div class="dropdown-item" style="cursor: pointer;"
ng-repeat="account in accounts"
ng-click="session.selectAccount(account)">
{{ account.name }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>

<!-- Step 2: Group -- "-->
<div ng-if="tabNavigation.activeTab == 1">
<h2 class="subtitle">Step 2: Choose or Create Group</h2>
<div class="row">
<div class="row-label">Metadata</div>
<div class="control">
<label class="radio">
<input type="radio" ng-model="session.formData.group.mode" value="create" name="group-metadata"
ng-change="session.createNewGroup()">
Create New
</label>
<label class="radio">
<input type="radio" ng-model="session.formData.group.mode" value="existing" name="group-metadata"
ng-disabled="session.groups.length == 0">
Use Existing Group
</label>
</div>
</div>

<div class="row" ng-if="session.formData.group.mode == 'existing'">
<div class="row-label">Name</div>
<div style="flex: 1">
<div class="dropdown is-hoverable">
<div class="dropdown-trigger">
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu">
<span>{{ session.accountData.name }}</span>
<span class="icon is-small">
<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu" role="menu">
<div class="dropdown-content">
<div class="dropdown-item" style="cursor: pointer;"
ng-repeat="account in accounts"
ng-click="session.selectAccount(account)">
{{ account.name }}
</div>
</div>
</div>
</div>
</div>
</div>

<div class="row" ng-if="session.formData.group.mode == 'create'">
<div class="row-label">Name</div>
<input type="text" class="input" ng-model="session.formData.group.name" ng-change="session.onChangeGroup()" value="existing">
</div>
<div class="row">
<div class="row-label">Title</div>
<input type="text" class="input" ng-model="session.formData.group.title" ng-change="session.onChangeGroup()" value="existing">
</div>

<!-- TODO: Add group list & create input -->
<button style="width: 100%; height: 3em;" ng-class=" { 'is-loading' : isPublishing }"
ng-disabled="isPublishing || !session.isReadyForUpload || !agreeCCZero" class="button is-primary"
ng-click="publish()">
<span>Publish</span>
</button>

</div>

<!-- Step 3: Artifact -->
<div ng-if="tabNavigation.activeTab == 2">
<h2 class="subtitle">Step 3: Choose or Create Artifact</h2>
<div class="row">
<div class="row-label">Metadata</div>
<div class="control">
<label class="radio">
<input type="radio" ng-model="session.formData.artifact.mode" value="create" name="artifact-metadata"
ng-change="session.createNewGroup()">
Create New
</label>
<label class="radio">
<input type="radio" ng-model="session.formData.artifact.mode" value="existing" name="artifact-metadata"
ng-disabled="session.groups.length == 0">
Use Existing Artifact
</label>
</div>
</div>

<div class="row" ng-if="session.formData.artifact.mode == 'existing'">
<div class="row-label">Name</div>
<div style="flex: 1">
<div class="dropdown is-hoverable">
<div class="dropdown-trigger">
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu">
<span>{{ session.accountData.name }}</span>
<span class="icon is-small">
<i class="fas fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu" role="menu">
<div class="dropdown-content">
<div class="dropdown-item" style="cursor: pointer;"
ng-repeat="account in accounts"
ng-click="session.selectAccount(account)">
{{ account.name }}
</div>
</div>
</div>
</div>
</div>
</div>

<div class="row" ng-if="session.formData.artifact.mode == 'create'">
<div class="row-label">Name</div>
<input type="text" class="input" ng-model="session.formData.artifact.name" ng-change="session.onChangeArtifact()" >
</div>
<div class="row">
<div class="row-label">Title</div>
<input type="text" class="input" ng-model="session.formData.artifact.title" ng-change="session.onChangeArtifact()" >
</div>
</div>

<!-- Step 4: Version -->
<div ng-if="tabNavigation.activeTab == 3">
<div class="box-content">
<h2 class="subtitle">Step 4: Choose or Create Version</h2>
<!-- TODO: Add version input, file uploader, metadata fields -->
</div>
</div>

</div>
</div>
</div>
</div>
</div>

<%- include('footer') -%>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Filename contains space and "copy" suffix.

The filename publish-wizard copy.ejs contains a space and the word "copy", suggesting this might be an unintentional duplicate or temporary file. This could cause issues with build tools and version control.

Clarify the intent of this file:

  • If this is a draft/experimental version, move it to a draft folder or use a clearer name
  • If this should replace the original, rename appropriately
  • If this is accidental, remove it

Check if this file is referenced anywhere:


🏁 Script executed:

#!/bin/bash
# Search for references to this template
rg -n "publish-wizard copy" --type js --type ejs

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Search for references to "publish-wizard copy" without file type restrictions
rg -n "publish-wizard copy" .

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for any references to this template file (broader search)
rg -n "publish-wizard" --type js --type json --type ts

Length of output: 55667


🏁 Script executed:

#!/bin/bash
# List all publish-wizard template files
fd "publish-wizard" . --type f

Length of output: 317


Remove unintentional duplicate template file.

The file public/templates/publish-wizard copy.ejs is not referenced anywhere in the codebase and appears to be an accidental copy. Only public/templates/publish-wizard.ejs is actively used by the application (referenced in server/app/webapp/modules/publish-wizard.js:27). Delete this orphaned file to keep the codebase clean.

🤖 Prompt for AI Agents
In public/templates/publish-wizard copy.ejs lines 1-320: this is an accidental
duplicate of publish-wizard.ejs and is not referenced by the app; delete the
file from the repository (git rm public/templates/publish-wizard copy.ejs), run
a quick project-wide search to confirm there are no remaining references, and
commit the removal with a clear message like "Remove accidental duplicate
template publish-wizard copy.ejs".

.wizard-step-tab.is-valid {
background-color: #d3f0c8;
border: 1px solid #78c04c;
color: 1px solid #78c04c;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

CSS property error: "color" should be "border".

Line 33 incorrectly uses the color property with a border value. This should be border-color or just border.

Apply this fix:

     .wizard-step-tab.is-valid {
       background-color: #d3f0c8;
       border: 1px solid #78c04c;
-      color: 1px solid #78c04c;
+      border-color: #78c04c;
     }

Or simply remove the line since border is already set on line 32.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
color: 1px solid #78c04c;
.wizard-step-tab.is-valid {
background-color: #d3f0c8;
border: 1px solid #78c04c;
border-color: #78c04c;
}
🤖 Prompt for AI Agents
In public/templates/publish-wizard copy.ejs around line 33, the CSS uses "color:
1px solid #78c04c;" which is invalid for borders; replace it with the correct
property (either "border: 1px solid #78c04c;" or "border-color: #78c04c;") or
remove the line entirely since a border is already defined on the previous line.

Comment on lines +191 to +200
<div ng-repeat="ns in secretary.hasWriteAccessTo track by $index" class="field has-addons mb-2">
<div class="control is-expanded">
<input class="input" type="text" ng-model="secretary.hasWriteAccessTo[$index]"
placeholder="Namespace IRI">
</div>
<div class="control">
<button class="button is-danger" ng-click="removeNamespace(activeAccount, $index, $index)">
<span class="icon"><i class="fas fa-times"></i></span>
</button>
</div>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Incorrect $index usage in nested ng-repeat.

Line 197 calls removeNamespace(activeAccount, $index, $index), but this is inside a nested ng-repeat. The outer loop (line 181) has its own $index, and the inner loop (line 191) redefines $index for the namespace list. Using $index twice will pass the namespace index for both parameters, not the secretary index.

Use $parent.$index to reference the outer loop's index:

-                  <button class="button is-danger" ng-click="removeNamespace(activeAccount, $index, $index)">
+                  <button class="button is-danger" ng-click="removeNamespace(activeAccount, $parent.$index, $index)">
                     <span class="icon"><i class="fas fa-times"></i></span>
                   </button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div ng-repeat="ns in secretary.hasWriteAccessTo track by $index" class="field has-addons mb-2">
<div class="control is-expanded">
<input class="input" type="text" ng-model="secretary.hasWriteAccessTo[$index]"
placeholder="Namespace IRI">
</div>
<div class="control">
<button class="button is-danger" ng-click="removeNamespace(activeAccount, $index, $index)">
<span class="icon"><i class="fas fa-times"></i></span>
</button>
</div>
<div ng-repeat="ns in secretary.hasWriteAccessTo track by $index" class="field has-addons mb-2">
<div class="control is-expanded">
<input class="input" type="text" ng-model="secretary.hasWriteAccessTo[$index]"
placeholder="Namespace IRI">
</div>
<div class="control">
<button class="button is-danger" ng-click="removeNamespace(activeAccount, $parent.$index, $index)">
<span class="icon"><i class="fas fa-times"></i></span>
</button>
</div>
🤖 Prompt for AI Agents
In public/templates/user-settings.ejs around lines 191 to 200, the
removeNamespace call uses $index for both the outer secretary index and the
inner namespace index; because this is inside a nested ng-repeat the outer
loop’s index is shadowed, so replace the first $index argument with
$parent.$index to pass the correct secretary index and keep the inner $index for
the namespace index (i.e. call removeNamespace(activeAccount, $parent.$index,
$index)).

@@ -0,0 +1,8 @@
<script>
var data = <%- JSON.stringify(data) %>;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Potential XSS vulnerability with unescaped JSON output.

Using <%- (unescaped output) with JSON.stringify(data) can introduce XSS vulnerabilities if the data object contains user-controlled input that hasn't been properly sanitized. The output is directly embedded in the script without escaping.

Apply this diff to use escaped output:

-  var data = <%- JSON.stringify(data) %>;
+  var data = <%= JSON.stringify(data) %>;

If you need unescaped output for a specific reason, ensure that all data is sanitized server-side before being passed to this template.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In public/templates/variables.ejs around line 2, the template currently uses
unescaped EJS output (<%- JSON.stringify(data) %>) which can inject raw user
content into the page and cause XSS; change it to use escaped output so the JSON
is HTML-escaped (use the escaped EJS tag for the serialized data) or, if you
must output raw JSON, first sanitize/escape all user-controlled fields
server-side and escape any "</" sequences before embedding, ensuring the
injected value cannot close the script tag or introduce HTML/JS.

var data = <%- JSON.stringify(data) %>;
var DATABUS_RESOURCE_BASE_URL = "<%= databus.resourceBaseUrl %>";
var DATABUS_DEFAULT_CONTEXT_URL = "<%= databus.defaultContextUrl %>";
var DATABUS_CONTEXT = <%- databus.context %>;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Potential XSS vulnerability with unescaped context output.

Using <%- (unescaped output) for databus.context can introduce XSS vulnerabilities if this value contains or could contain user-controlled input.

Unless you have a specific need for unescaped HTML output here, use escaped output:

-  var DATABUS_CONTEXT =  <%- databus.context %>;
+  var DATABUS_CONTEXT =  <%= JSON.stringify(databus.context) %>;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var DATABUS_CONTEXT = <%- databus.context %>;
var DATABUS_CONTEXT = <%= JSON.stringify(databus.context) %>;
🤖 Prompt for AI Agents
In public/templates/variables.ejs around line 5, the template uses unescaped
output for databus.context which can introduce XSS; replace the unescaped output
with an escaped, JSON-serialized value so the context is safely embedded as a JS
value (serialize databus.context on the server with JSON.stringify and render it
using EJS escaped output instead of <%-), ensuring the resulting string is
properly quoted/escaped for JavaScript.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Review continued from previous batch...

Comment on lines +10694 to +10698
.databus-navbar .nav-search .nav-search input:focus {
border-color: #c3d2e4;
box-shadow: none;
}
.databus-navbar .nav-search .results {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Likely selector typo prevents focus styles

“.nav-search .nav-search input:focus” duplicates the class and won’t match typical markup.

-.databus-navbar .nav-search .nav-search input:focus {
+.databus-navbar .nav-search input:focus {
   border-color: #c3d2e4;
   box-shadow: none;
 }
```<!-- review_comment_end -->

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
.databus-navbar .nav-search input:focus {
  border-color: #c3d2e4;
  box-shadow: none;
}
.databus-navbar .nav-search .results {
🤖 Prompt for AI Agents
In public/css/website.css around lines 10694 to 10698, the selector
".databus-navbar .nav-search .nav-search input:focus" mistakenly repeats
".nav-search" so the focus styles won't apply; update the selector to target the
input correctly (e.g., ".databus-navbar .nav-search input:focus") and remove the
duplicated class so the border-color and box-shadow rules apply as intended.

Comment on lines +10731 to +10734
display: box;
color: white;
}
.databus-navbar .nav-search .results::-webkit-scrollbar {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Invalid display value “box”

"display: box" is obsolete and ignored. Use block/flex.

-.databus-navbar .nav-search .results .result-item .item-header {
-  display: box;
+.databus-navbar .nav-search .results .result-item .item-header {
+  display: block; /* or: display:flex; align-items:center; */
   color: white;
 }
```<!-- review_comment_end -->


> Committable suggestion skipped: line range outside the PR's diff.

<details>
<summary>🤖 Prompt for AI Agents</summary>

In public/css/website.css around lines 10731 to 10734, the rule uses the
obsolete value "display: box" which is ignored by modern browsers; replace it
with an appropriate modern display value (e.g., display: block; or display:
flex;) depending on the intended layout and adjust any related child styling if
switching to flex (justify-content, align-items) to preserve layout.


</details>

<!-- fingerprinting:phantom:triton:chinchilla -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +10779 to +10785
.databus-navbar .nav-search .result-item .item-abstract {
color: white;
width: 620px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Hard width on search abstracts hurts responsiveness

Fixed 620px truncates on small screens; prefer fluid max-width with ellipsis.

-.databus-navbar .nav-search .results .result-item .item-abstract {
-  color: white;
-  width: 620px;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  overflow: hidden;
-}
+.databus-navbar .nav-search .results .result-item .item-abstract {
+  color: white;
+  max-width: min(60ch, 55vw);
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  overflow: hidden;
+}
```<!-- review_comment_end -->


> Committable suggestion skipped: line range outside the PR's diff.

<details>
<summary>🤖 Prompt for AI Agents</summary>

public/css/website.css around lines 10779-10785: the .databus-navbar .nav-search
.result-item .item-abstract rule uses a fixed width: 620px which breaks
responsiveness; replace the fixed width with a fluid layout by using width: 100%
and max-width: 620px (and keep text-overflow, white-space, overflow as-is) so
the element can shrink on small screens while retaining the 620px cap on larger
screens.


</details>

<!-- fingerprinting:phantom:triton:chinchilla -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +10864 to +10874
.frontpage-box:hover {
-moz-transform: translateY(-4px);
-webkit-transform: translateY(-4px);
-o-transform: translateY(-4px);
-ms-transform: translateY(-4px);
-webkit-transform: translateY(-4px);
transform: translateY(-4px);
-webkit-transition: transform 0.4s ease-out;
-moz-transition: transform 0.4s ease-out;
-ms-transition: transform 0.4s ease-out;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Duplicate -webkit-transform; remove legacy prefixes

Duplicate -webkit-transform and obsolete -o/-ms prefixes; keep modern transform (and -webkit if you must). Based on static analysis hints

 .frontpage-box:hover {
-  -moz-transform: translateY(-4px);
-  -webkit-transform: translateY(-4px);
-  -o-transform: translateY(-4px);
-  -ms-transform: translateY(-4px);
-  -webkit-transform: translateY(-4px);
-  transform: translateY(-4px);
+  transform: translateY(-4px);
   -webkit-transition: transform 0.4s ease-out;
   -moz-transition: transform 0.4s ease-out;
   -ms-transition: transform 0.4s ease-out;
 }
```<!-- review_comment_end -->

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
.frontpage-box:hover {
  transform: translateY(-4px);
  -webkit-transition: transform 0.4s ease-out;
  -moz-transition: transform 0.4s ease-out;
  -ms-transition: transform 0.4s ease-out;
}
🧰 Tools
🪛 Biome (2.1.2)

[error] 10869-10869: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

-webkit-transform is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🤖 Prompt for AI Agents
In public/css/website.css around lines 10864 to 10874, the .frontpage-box:hover
block contains a duplicate -webkit-transform line and obsolete vendor prefixes
(-o-, -ms-, and -moz-) for transform and transition; remove the duplicate
-webkit-transform and drop the -o-, -ms-, and -moz- prefixed
transform/transition rules, keeping only the standard transform and transition
declarations and an optional single -webkit- fallback (i.e., keep transform and
transition, plus one -webkit-transform and/or one -webkit-transition if you want
legacy WebKit support).

Comment on lines +12250 to +12252
.field.has-addons input.control:first-child {
border-radius: 4px 0px 0px 4px;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Selector likely incorrect for Bulma addons radius

Bulma structure is .field.has-addons .control:first-child .input, not input.control:first-child. Current selector may never apply.

-.field.has-addons input.control:first-child {
+.field.has-addons .control:first-child .input {
   border-radius: 4px 0px 0px 4px;
 }
```<!-- review_comment_end -->

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
.field.has-addons .control:first-child .input {
  border-radius: 4px 0px 0px 4px;
}
🤖 Prompt for AI Agents
In public/css/website.css around lines 12250 to 12252, the selector
.field.has-addons input.control:first-child is incorrect for Bulma addon
controls and likely never matches; change the selector to target the input
inside the first .control in a has-addons field (e.g. .field.has-addons
.control:first-child .input) and apply the same border-radius declaration there
so the left-most input gets border-radius: 4px 0 0 4px.

Comment on lines +359 to +379
onChangeGroup() {

let group = this.formData.group;

group.errors = [];
group.warnings = [];

if (!DatabusUtils.isValidGroupName(group.name)) {
group.errors.push('err_invalid_group_name');
}

var existingGroup = this.groups.filter(function (value) {
return value.name == self.group.name;
});

if (existingGroup.length > 0 && group.mode == 'create') {
group.warnings.push('warning_group_exists');
}

this.save();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Prevent crash in onChangeGroup.

self is not defined here, so the first time this.groups.filter(...) runs you hit ReferenceError: self is not defined. On top of that, this.groups may still be undefined before the SPARQL fetch completes, leading to TypeError: Cannot read properties of undefined (reading 'filter'). Guard the array and close over group instead.

-        var existingGroup = this.groups.filter(function (value) {
-            return value.name == self.group.name;
-        });
+        const groups = Array.isArray(this.groups) ? this.groups : [];
+        const existingGroup = groups.filter(value => value.name === group.name);
🤖 Prompt for AI Agents
In public/js/publish/publish-session.js around lines 359 to 379, onChangeGroup
uses an undefined self and assumes this.groups exists; replace the self
reference by closing over the local group variable (use the already-declared
group), and guard against missing groups by filtering a safe array (e.g.
(this.groups || [])). Update the existingGroup computation to use group.name
instead of self.group.name and ensure this.groups is defaulted to an empty array
before calling filter, then leave the rest of the logic (pushing errors/warnings
and this.save()) unchanged.

Comment on lines +414 to +435
onChangeArtifact() {

let artifact = this.formData.artifact;

artifact.errors = [];
artifact.warnings = [];

if (!DatabusUtils.isValidArtifactName(artifact.name)) {
artifact.errors.push('err_invalid_artifact_name');
}

if (this.artifacts != null) {
var existingArtifact = this.artifacts.filter(function (value) {
return value.name == self.group.name;
});

if (existingArtifact.length > 0 && artifact.mode == 'create') {
artifact.warnings.push('warning_group_exists');
}
}

this.save();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix duplicate-artifact detection in onChangeArtifact.

Same self reference leads to a ReferenceError, and comparing against self.group.name never flags the actual artifact duplicates. Guard the list and compare to the artifact name instead so warnings work without exploding.

-        if (this.artifacts != null) {
-            var existingArtifact = this.artifacts.filter(function (value) {
-                return value.name == self.group.name;
-            });
-
-            if (existingArtifact.length > 0 && artifact.mode == 'create') {
-                artifact.warnings.push('warning_group_exists');
-            }
-        }
+        const artifacts = Array.isArray(this.artifacts) ? this.artifacts : [];
+        const existingArtifact = artifacts.filter(value => value.name === artifact.name);
+
+        if (existingArtifact.length > 0 && artifact.mode === 'create') {
+            artifact.warnings.push('warning_group_exists');
+        }
🤖 Prompt for AI Agents
In public/js/publish/publish-session.js around lines 414 to 435, the
onChangeArtifact function uses an undefined self and compares existing artifact
names to self.group.name which causes a ReferenceError and never detects
duplicates; update the block to guard that this.artifacts is an array, use this
(not self) and compare value.name to artifact.name (and optionally exclude the
same artifact if there's an id/unique key or when mode !== 'create'), pushing
the warning when a match is found and artifact.mode === 'create'; then call
this.save() as before.

Comment on lines +131 to +134
const exists = this.artifactList?.some(a => a.name === this.name);
if (exists) {
this.warnings.push('warning_artifact_exists');
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use the version list when warning about duplicates.

validate() is checking artifactList for this.name, so it never warns if the version already exists (unless an artifact accidentally shares the same identifier). This regresses the duplicate-version warning and lets the user run into server-side conflicts. Use the freshly fetched versionList instead.

-    const exists = this.artifactList?.some(a => a.name === this.name);
+    const exists = this.versionList?.some(v => v.name === this.name);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const exists = this.artifactList?.some(a => a.name === this.name);
if (exists) {
this.warnings.push('warning_artifact_exists');
}
const exists = this.versionList?.some(v => v.name === this.name);
if (exists) {
this.warnings.push('warning_artifact_exists');
}
🤖 Prompt for AI Agents
In public/js/publish/version-handler.js around lines 131 to 134, the current
duplicate check uses this.artifactList and this.name which misses
already-fetched versions; change it to check the freshly fetched
this.versionList (null-safe) for an entry matching the current version (e.g.
versionList.some(v => v.version === this.version)) and push the
duplicate-version warning (use the appropriate warning key such as
'warning_version_exists' or update the existing message) so the client warns
about duplicate versions before submitting.

Comment on lines +11 to +83
static async createAccountGraphs(uri, name, label, img, secretaries, status) {
var name = UriUtils.uriToName(uri);

var rsaKeyGraph = {};
rsaKeyGraph[DatabusUris.JSONLD_TYPE] = DatabusUris.CERT_RSA_PUBLIC_KEY;
rsaKeyGraph[DatabusUris.RDFS_LABEL] = DatabusConstants.WEBID_SHARED_PUBLIC_KEY_LABEL;
rsaKeyGraph[DatabusUris.CERT_MODULUS] = signer.getModulus();
rsaKeyGraph[DatabusUris.CERT_EXPONENT] = 65537;

var personUri = `${uri}${DatabusConstants.WEBID_THIS}`;

var accountUri = `${resourceBaseUrl}/${accountName}`;
var profileUri = `${resourceBaseUrl}/${accountName}${DatabusConstants.WEBID_DOCUMENT}`;
var personUri = `${resourceBaseUrl}/${accountName}${DatabusConstants.WEBID_THIS}`;
var personGraph = {};
personGraph[DatabusUris.JSONLD_ID] = personUri;
personGraph[DatabusUris.JSONLD_TYPE] = [ DatabusUris.FOAF_PERSON, DatabusUris.DBP_DBPEDIAN ];
personGraph[DatabusUris.FOAF_ACCOUNT] = JsonldUtils.refTo(uri);
personGraph[DatabusUris.DATABUS_ACCOUNT_PROPERTY] = uri;
personGraph[DatabusUris.CERT_KEY] = [ rsaKeyGraph ];
personGraph[DatabusUris.FOAF_NAME] = label;

if(img != null) {
personGraph[DatabusUris.FOAF_IMG] = img;
}

if(status != null) {
personGraph[DatabusUris.FOAF_STATUS] = status;
}

var profileUri = `${uri}${DatabusConstants.WEBID_DOCUMENT}`;

var profileDocumentGraph = {};
profileDocumentGraph[DatabusUris.JSONLD_ID] = profileUri;
profileDocumentGraph[DatabusUris.JSONLD_TYPE] = DatabusUris.FOAF_PERSONAL_PROFILE_DOCUMENT;
profileDocumentGraph[DatabusUris.FOAF_MAKER] = JsonldUtils.refTo(personUri);
profileDocumentGraph[DatabusUris.FOAF_PRIMARY_TOPIC] = JsonldUtils.refTo(personUri);

var accountGraph = {}
accountGraph[DatabusUris.JSONLD_ID] = uri;
accountGraph[DatabusUris.JSONLD_TYPE] = DatabusUris.DATABUS_ACCOUNT;
accountGraph[DatabusUris.FOAF_ACCOUNT_NAME] = name;
accountGraph[DatabusUris.DATABUS_NAME] = name;

if(secretaries != null) {

accountGraph[DatabusUris.DATABUS_SECRETARY_PROPERTY] = [];

for(var secretary of secretaries) {

let secretaryAccountUri = `${secretary.accountName}`;

let secretaryGraph = {};
secretaryGraph[DatabusUris.JSONLD_TYPE] = DatabusUris.DATABUS_SECRETARY;
secretaryGraph[DatabusUris.DATABUS_ACCOUNT_PROPERTY] = JsonldUtils.refTo(secretaryAccountUri);

if(secretary.hasWriteAccessTo != undefined) {
secretaryGraph[DatabusUris.DATABUS_HAS_WRITE_ACCESS_TO] = [];

for(var writeAccess of secretary.hasWriteAccessTo) {
secretaryGraph[DatabusUris.DATABUS_HAS_WRITE_ACCESS_TO].push(JsonldUtils.refTo(writeAccess));
}
}

accountGraph[DatabusUris.DATABUS_SECRETARY_PROPERTY].push(secretaryGraph);
}
}

let expandedGraphs = [
accountGraph,
personGraph,
profileDocumentGraph
];

return await jsonld.compact(expandedGraphs, JsonldLoader.DEFAULT_CONTEXT_URL);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Resolve undefined identifiers in createAccountGraphs

createAccountGraphs now references UriUtils, signer, jsonld, and JsonldLoader, but none of these symbols are imported or defined in this module. As written the very first call will throw ReferenceError, breaking any feature that relies on graph generation. Please add the appropriate require statements (or reuse existing helpers such as DatabusUtils.uriToResourceName) and make sure signer is available in scope before shipping.

🧰 Tools
🪛 Biome (2.1.2)

[error] 12-12: Shouldn't redeclare 'name'. Consider to delete it or rename it.

'name' is defined here:

(lint/suspicious/noRedeclare)

🤖 Prompt for AI Agents
In public/js/utils/app-json-formatter.js lines 11-83, the function
createAccountGraphs uses undefined identifiers UriUtils, signer, jsonld and
JsonldLoader which will throw ReferenceError; fix by either
importing/require-ing the missing modules at the top (e.g. const jsonld =
require('jsonld'); const UriUtils = require('./uri-utils') or the correct path;
const JsonldLoader = require('./jsonld-loader')), or replace UriUtils.uriToName
with the existing DatabusUtils.uriToResourceName helper; ensure signer is in
scope by importing the signer module or by changing the function signature to
accept a signer parameter and passing it from callers; finally update any call
sites if you change the signature and run linter/tests to verify no other
missing symbols remain.

Comment on lines +585 to 593
<div class="control">
<button class="button is-link"
ng-click="session.version.addContentVariant(session.version.contentVariantInput); showAddVariantForm = false;">Add
Content Variant</button>
</div>
<div class="databus-settings-info" style="margin-bottom: 10px">
<div>Click the <b>Create Tractate</b> button to generate the tractate for your metadata
document. The Databus tractate is a minimal canonicalized form of your document containing
the most crucial pieces of information. Sign the tractate with your private key and post the
signature into the field below.</div>
<div class="control">
<button class="button is-light"
ng-click="session.version.showAddVariantForm = false">Cancel</button>
</div>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep showAddVariantForm on session.version

The new button handler assigns showAddVariantForm = false; without the session.version qualifier. That writes to the parent scope, so the form never closes and the local flag stays true. Please update the expression to reset session.version.showAddVariantForm instead.

-                          ng-click="session.version.addContentVariant(session.version.contentVariantInput); showAddVariantForm = false;">Add
+                          ng-click="session.version.addContentVariant(session.version.contentVariantInput); session.version.showAddVariantForm = false;">Add
🤖 Prompt for AI Agents
In public/templates/publish-wizard.ejs around lines 585 to 593, the Add Content
Variant button's ng-click assigns showAddVariantForm = false without the
session.version qualifier which writes to the parent scope and doesn't close the
form; change the expression to set session.version.showAddVariantForm = false so
the flag on the version object is reset (mirror the Cancel button's
session.version.showAddVariantForm = false).

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.

4 participants