Skip to content

Conversation

@grahampacker-ms
Copy link
Member

@grahampacker-ms grahampacker-ms commented Jan 28, 2026

Description

Changed the namespace to a full object from a simple string. This will allow future extension without breaking change. This is a data model change so will break existing calm hubs. Given calm-hub is not ready for proper usage I don't think a migration guide is needed.

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🎨 Code style/formatting changes
  • ♻️ Refactoring (no functional changes)
  • ⚡ Performance improvements
  • ✅ Test additions or updates
  • 🔧 Chore (maintenance, dependencies, CI, etc.)

Affected Components

  • CLI (cli/)
  • Shared (shared/)
  • CALM Widgets (calm-widgets/)
  • CALM Hub (calm-hub/)
  • CALM Hub UI (calm-hub-ui/)
  • Documentation (docs/)
  • VS Code Extension (calm-plugins/vscode/)
  • Dependencies
  • CI/CD

Commit Message Format ✅

Testing

  • I have tested my changes locally
  • I have added/updated unit tests
  • All existing tests pass

Checklist

  • My commits follow the conventional commit format
  • I have updated documentation if necessary
  • I have added tests for my changes (if applicable)
  • My changes follow the project's coding standards

@markscott-ms
Copy link
Contributor

@grahampacker-ms @willosborne could we have a wider discussion on the roadmap for CalmHub and how these individual changes align to how entitlements, immutable artifact repository, etc, are aligned?

@grahampacker-ms grahampacker-ms force-pushed the issue-1440-namespace-refactor branch 2 times, most recently from 70d5a49 to e3278ef Compare January 28, 2026 20:47
@grahampacker-ms grahampacker-ms changed the title feat(calm-hub): refactored namespaces from simple string to full obje… feat(calm-hub): refactored namespaces from simple string to full obect and added description Jan 29, 2026
…ct and added description

# Conflicts:
#	package-lock.json
@markscott-ms
Copy link
Contributor

@grahampacker-ms and I had a conversation. happy for this PR to proceed - in fact it is definitely necessary.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors the namespace representation from a simple string to a full object with name and description fields. This is a breaking change that enables future extensibility without additional breaking changes. The refactoring affects both the calm-hub backend and calm-hub-ui frontend.

Changes:

  • Introduced a new NamespaceInfo class with name and description fields
  • Updated NamespaceRequest to include a description field alongside the name field
  • Modified all store implementations (Nitrite and MongoDB) to handle the new namespace structure
  • Updated database initialization scripts and integration tests to use the new format
  • Adapted the UI service to extract name values from the new namespace objects

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
calm-hub/src/main/java/org/finos/calm/domain/namespaces/NamespaceInfo.java New domain class representing namespace information with name and description
calm-hub/src/main/java/org/finos/calm/domain/NamespaceRequest.java Updated to replace namespace field with name and added description field
calm-hub/src/main/java/org/finos/calm/store/NamespaceStore.java Updated interface to return NamespaceInfo objects and accept separate name/description parameters
calm-hub/src/main/java/org/finos/calm/store/nitrite/NitriteNamespaceStore.java Updated to store and retrieve namespace objects with name and description fields
calm-hub/src/main/java/org/finos/calm/store/mongo/MongoNamespaceStore.java Updated to store and retrieve namespace objects with name and description fields
calm-hub/src/main/java/org/finos/calm/resources/NamespaceResource.java Updated to handle the new namespace structure in API requests and responses
calm-hub/src/test/java/org/finos/calm/store/nitrite/TestNitriteNamespaceStoreShould.java Updated tests to work with NamespaceInfo objects
calm-hub/src/test/java/org/finos/calm/store/mongo/TestMongoNamespaceStoreShould.java Updated tests to work with NamespaceInfo objects
calm-hub/src/test/java/org/finos/calm/resources/TestNamespaceResourceShould.java Updated tests for new API structure and removed redundant comments
calm-hub/src/integration-test/java/integration/PermittedScopesIntegration.java Updated to verify both name and description fields in responses
calm-hub/src/integration-test/java/integration/MongoNamespaceIntegration.java Updated to verify both name and description fields in responses
calm-hub/src/integration-test/java/integration/MongoSetup.java Updated test data to include description field
calm-hub/mongo/init-mongo.js Updated initialization script to use new namespace structure
calm-hub-ui/src/service/calm-service.tsx Updated to extract name values from the new namespace object structure

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +8 to +27
public class NamespaceInfo {
@NotNull(message = "Name must not be null")
@NotBlank(message = "Name must not be blank")
private final String name;
private final String description;

public NamespaceInfo(String name, String description) {
this.name = name;
this.description = description;
}

public String getName() {
return name;
}

public String getDescription() {
return description;
}

}
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The NamespaceInfo class is missing equals() and hashCode() implementations. Since this class is used in collections and comparisons (as seen in test assertions), it should implement these methods to ensure proper equality checks. This is especially important for the domain model where objects may be compared or used in Sets/Maps.

Copilot uses AI. Check for mistakes.
@NotNull(message = "Name must not be null")
@NotBlank(message = "Name must not be blank")
private String name;

Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The description field has no validation annotations. Unlike the name field which has @NotNull and @notblank, the description field allows null values. This inconsistency could lead to issues when storing descriptions. Consider adding validation constraints if descriptions are required, or explicitly document that null descriptions are acceptable.

Suggested change
@NotNull(message = "Description must not be null")
@NotBlank(message = "Description must not be blank")

Copilot uses AI. Check for mistakes.
const data = await res.json();
setNamespaces(data.values);
const values = Array.isArray(data?.values) ? data.values : [];
const namespaces = values.map((v: { name?: string }) => v?.name);
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The mapping from namespace objects to names can produce undefined values in the array. If a namespace object is missing the name property, v?.name will be undefined, resulting in an array that might contain undefined values. Consider filtering out undefined values or handling this edge case more explicitly.

Suggested change
const namespaces = values.map((v: { name?: string }) => v?.name);
const namespaces = values
.map((v: { name?: string }) => v?.name)
.filter((name): name is string => typeof name === 'string');

Copilot uses AI. Check for mistakes.

String namespace = request.getNamespace().trim();
String name = request.getName().trim();
String description = request.getDescription();
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The description parameter is not validated before being passed to the store. If the description is null, it will be stored as null in the database. While NamespaceRequest allows null descriptions, the NamespaceResource should handle this case explicitly, either by validating that description is not null or by providing a default value. Consider adding null handling here to ensure consistent behavior.

Suggested change
String description = request.getDescription();
String description = request.getDescription();
if (description != null) {
description = description.trim();
} else {
description = "";
}

Copilot uses AI. Check for mistakes.

String namespace = request.getNamespace().trim();
String name = request.getName().trim();
String description = request.getDescription();
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The name field is trimmed before use, but the description field is not. If users submit descriptions with leading or trailing whitespace, this will be stored as-is. Consider trimming the description as well for consistency, or document why descriptions should preserve whitespace while names should not.

Suggested change
String description = request.getDescription();
String description = request.getDescription();
if (description != null) {
description = description.trim();
}

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +59
assertThat(result.get(0).getName(), is("finos"));
assertThat(result.get(1).getName(), is("workshop"));
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The test only verifies the name field of the returned NamespaceInfo objects but doesn't verify the description field. Since the test documents include descriptions ("d1" and "d2"), add assertions to verify these descriptions are correctly retrieved.

Copilot uses AI. Check for mistakes.
Comment on lines +70 to +71
assertThat(namespaces.get(0).getName(), is(expectedNamespaces.get(0).getName()));
assertThat(namespaces.get(1).getName(), is(expectedNamespaces.get(1).getName()));
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The test only verifies the name field but not the description field. Add assertions to verify that the descriptions ("FINOS namespace" and "other namespace") are correctly retrieved from the documents.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants