Skip to content

Smoke Testing Docker and adding CalmHub Docs#2615

Closed
jpgough-ms wants to merge 26 commits into
finos:mainfrom
jpgough-ms:smoking-docker
Closed

Smoke Testing Docker and adding CalmHub Docs#2615
jpgough-ms wants to merge 26 commits into
finos:mainfrom
jpgough-ms:smoking-docker

Conversation

@jpgough-ms

Copy link
Copy Markdown
Member

Description

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/)
  • Schema (calm/)
  • CALM AI (calm-ai/)
  • CALM Hub (calm-hub/)
  • CALM Hub UI (calm-hub-ui/)
  • CALM Server (calm-server/)
  • CALM Widgets (calm-widgets/)
  • Documentation (docs/)
  • Shared (shared/)
  • 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

- Rewrite docker-publish-calm-hub-native.yml and
  docker-publish-calm-hub-readonly-native.yml to use a per-architecture
  build matrix (ubuntu-latest for amd64, ubuntu-24.04-arm for arm64).
  Each runner compiles the native binary for its own architecture via
  Quarkus container-build (no QEMU), pushes the image by digest, then
  the merge job assembles a single multi-arch manifest via
  'docker buildx imagetools create'.

- Add Docker smoke tests to all four publish workflows that gate the
  push step: a locally-loaded single-arch image is started, assertions
  are run against the live API, and only on success is the image pushed.
  Mongo-backed images (jvm, native) spin up a transient mongo:8
  container on a private Docker network.  Read-only images (readonly-
  static, readonly-native) are self-contained.  Container logs are
  dumped on failure for debugging.

- Add calm-hub/smoke-test.sh: shared assertion script used by all four
  workflows.  Polls /q/swagger-ui for readiness, then asserts in
  readonly mode (GET 200, POST/PUT/DELETE 405) and readwrite mode
  (GET 200, POST 201).  Verified locally against calm-hub:read-only-
  native and calm-hub:native.
Add a dedicated CALM Hub docs section (navbar left of CALM Studio):
- docs/docs/calm-hub/index.md: features, all four image variants, read-only
  mode + two-stage data-image-layer explanation, GitHub Actions build-status
  badges for all 6 workflows, Docker Hub image links (finos/calm-hub).
- docs/docs/calm-hub/developer-guide.md: test pyramid (unit / integration /
  smoke), storage-layer extension guide (Store interfaces + CDI producers),
  build scripts reference, configuration table.
- docs/docs/calm-hub/mcp-and-api.md: MCP endpoint (/mcp, enabling flag,
  tool list, curl examples, client config), OpenAPI/Swagger UI reference.

Wire up navigation:
- docs/sidebars.js: add calmHubSidebar with the three new pages.
- docs/docusaurus.config.js: insert 'CALM Hub' navbar item left of 'CALM Studio'.
- docs/docs/working-with-calm/calm-hub.md: add tip callout linking to new section.

Update calm-hub/AGENTS.md: document read-only mode, two-stage image layer,
four image variants, build scripts, smoke-test.sh usage, MCP server, and
docker-publish workflow table (with correct trigger paths).

Fix CI workflow bugs:
- docker-publish-calm-hub-readonly.yml: remove duplicate bare '- name: Build
  and push' step that would cause a YAML parse error on the publish job.
- docker-publish-calm-hub-native.yml,
  docker-publish-calm-hub-readonly-native.yml: add 'calm-hub-ui/**' to push
  trigger paths. The calm-hub Maven build runs the UI production build
  (calm-hub-ui:prod) as part of the package phase, so UI changes must
  re-trigger native image builds.
…ests

- Correct ASCII test pyramid in developer-guide.md (box was 22 chars wide
  but content needed 23 chars; rebuilt at 28 chars with proper alignment
  and <- arrow annotations).
- Remove all em dashes from the three calm-hub docs pages; replace with
  hyphens or restructured prose.
- Expand smoke-test.sh: readonly mode now GETs finos/architectures,
  finos/patterns, and traderx/architectures in addition to blocking
  mutation checks; readwrite mode creates a namespace, creates an
  architecture, then retrieves by list (/architectures), version list
  (/architectures/1/versions), and specific version
  (/architectures/1/versions/1.0.0).
Move the CALM Hub UI walkthrough out of the Working with CALM sidebar
and into calmHubSidebar so all four CALM Hub pages (overview, UI
walkthrough, developer guide, MCP/API) live under the CALM Hub top-bar
section. The page keeps its /working-with-calm/calm-hub URL so existing
links do not break; its sidebar label is now 'UI Walkthrough' and the
tip box points to the technical reference pages.
@github-actions github-actions Bot added calm-hub Affects `calm-hub` docs Improvements of additions to documentation labels Jun 9, 2026
@github-actions github-actions Bot added the calm-hub-ui Affects `calm-hub-ui` label Jun 11, 2026
jpgough-ms and others added 3 commits June 11, 2026 13:37
…iles

- Single calm-hub/deploy/docker-compose.yml with four profiles (jvm, native, readonly-static, readonly-native), one per published image variant. Each binds 8080:8080; jvm and native include a MongoDB sidecar via service-level profiles, the readonly variants are self-contained.

- Add calm-hub/deploy/.env with COMPOSE_PROFILES=jvm so plain 'docker compose up' continues to launch the JVM image (no UX change for the default Quick Start path).

- Remove calm-hub/deploy-native/ — its single compose file is now the 'native' profile in the consolidated compose, preserving the QUARKUS_PROFILE=no-auth + CALM_AUTH_ENABLED=false local UX.

- README Quick Start: replace the @jpgough-ms manual-build note with a profile table and 'docker compose --profile <name> up' examples for all four variants.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 adds CALM Hub–focused documentation to the Docusaurus site, introduces a shared Docker smoke-test script, and updates Dockerfiles/CI workflows to validate CALM Hub image variants (including native + read-only) before publishing.

Changes:

  • Add a dedicated “CALM Hub” docs sidebar and new CALM Hub docs pages (overview, developer guide, MCP/API reference), plus a UI walkthrough entry.
  • Add calm-hub/smoke-test.sh and integrate smoke-testing into Docker publish GitHub Actions workflows.
  • Fix native image runtime compatibility by staging libz.so.1 into distroless-based native images; add native-image reflection registrations for summary DTOs.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
docs/sidebars.js Removes CALM Hub doc from the general “Working with CALM” category and adds a dedicated calmHubSidebar.
docs/docusaurus.config.js Adds a “CALM Hub” navbar item pointing at the new docs sidebar.
docs/docs/working-with-calm/calm-hub.md Updates sidebar label and adds a doc cross-link tip for CALM Hub technical references.
docs/docs/calm-hub/index.md New CALM Hub overview doc covering features, runtimes, image variants, and quick start.
docs/docs/calm-hub/developer-guide.md New developer guide describing project structure, test pyramid, storage architecture, and build scripts.
docs/docs/calm-hub/mcp-and-api.md New MCP + REST API reference doc (OpenAPI endpoints, MCP enablement, tool list, examples).
calm-hub/src/main/java/org/finos/calm/domain/timeline/NamespaceTimelineSummary.java Registers DTO for reflection to avoid native serialization issues.
calm-hub/src/main/java/org/finos/calm/domain/standards/NamespaceStandardSummary.java Registers DTO for reflection to avoid native serialization issues.
calm-hub/src/main/java/org/finos/calm/domain/ResourceMapping.java Registers DTO for reflection to avoid native serialization issues.
calm-hub/src/main/java/org/finos/calm/domain/pattern/NamespacePatternSummary.java Registers DTO for reflection to avoid native serialization issues.
calm-hub/src/main/java/org/finos/calm/domain/interfaces/NamespaceInterfaceSummary.java Registers DTO for reflection to avoid native serialization issues.
calm-hub/src/main/java/org/finos/calm/domain/flow/NamespaceFlowSummary.java Registers DTO for reflection to avoid native serialization issues.
calm-hub/src/main/java/org/finos/calm/domain/architecture/NamespaceArchitectureSummary.java Registers DTO for reflection to avoid native serialization issues.
calm-hub/src/main/java/org/finos/calm/domain/adr/NamespaceAdrSummary.java Registers DTO for reflection to avoid native serialization issues.
calm-hub/src/main/docker/Dockerfile.native Adds a build stage to copy libz.so.1 into the distroless native runtime image.
calm-hub/src/main/docker/Dockerfile.readonly-native Adds a build stage to copy libz.so.1 into the distroless read-only native runtime image.
calm-hub/smoke-test.sh New smoke-test script for readwrite/readonly image API contract validation.
calm-hub/README.md Updates local Docker quick start instructions and documents compose profiles per image variant.
calm-hub/deploy/docker-compose.yml Consolidates local compose into a single file with four profiles (jvm/native/readonly-static/readonly-native).
calm-hub/deploy/.env Adds default COMPOSE_PROFILES=jvm for compose profile selection.
calm-hub/deploy-native/docker-compose.yml Removes now-redundant native-only compose file.
calm-hub/AGENTS.md Documents image variants, smoke tests, and MCP server details for contributors/agents.
calm-hub-ui/src/service/calm-service.tsx Hardens version-fetching calls to return [] if API response shape is unexpected.
calm-hub-ui/src/service/adr-service/adr-service.tsx Hardens ADR revision fetching to return [] if API response shape is unexpected.
calm-hub-ui/src/hub/components/tree-navigation/TreeNavigation.tsx Avoids toString() on null/undefined IDs; filters invalid resource IDs/names.
calm-hub-ui/index.html Removes unused output.css link from the HTML entrypoint.
.github/workflows/docker-publish-calm-hub.yml Adds a build+run smoke test step before pushing the JVM (Mongo-backed) image.
.github/workflows/docker-publish-calm-hub-readonly.yml Adds a build+run smoke test step before pushing the read-only JVM image.
.github/workflows/docker-publish-calm-hub-native.yml Refactors native publishing to per-arch build/smoke/push-by-digest + merge manifest.
.github/workflows/docker-publish-calm-hub-readonly-native.yml Refactors read-only native publishing to per-arch build/smoke/push-by-digest + merge manifest.

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

Comment thread docs/docs/working-with-calm/calm-hub.md Outdated
Comment thread docs/docs/calm-hub/mcp-and-api.md Outdated
Comment thread calm-hub/AGENTS.md Outdated
jpgough-ms and others added 3 commits June 11, 2026 16:31
fix(docs): Suggestion from co-pilot

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Addresses Copilot review on PR finos#2615: calm-hub/pom.xml overrides io.quarkiverse.mcp:quarkus-mcp-server-http to 1.12.1, but two docs still cited 1.12.0. Bring them in line so contributors land on the right release notes / native-image fix level.
Comment thread calm-hub/AGENTS.md
|:-------------|:----------|:-------------------------------|
| `docker-publish-calm-hub.yml` | `latest` | `calm-hub/**`, `calm-hub-ui/**` |
| `docker-publish-calm-hub-native.yml` | `latest-native` | `calm-hub/**`, `calm-hub-ui/**` |
| `docker-publish-calm-hub-readonly.yml` | `latest-read-only-static` | `calm-hub/**`, `calm-hub-ui/**`, `calm/**` |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This row lists calm-hub-ui/** as a trigger path for the read-only static workflow, but docker-publish-calm-hub-readonly.yml doesn't actually include it — its paths: filter is only calm-hub/**, calm/**, and the workflow file itself. The other three workflows (jvm, native, and read-only native) all do list calm-hub-ui/**, so this one is the odd one out.

Since the read-only image bundles the UI build, a UI-only change won't rebuild/republish latest-read-only-static. Two ways to reconcile:

  • add - 'calm-hub-ui/**' to the paths: block in docker-publish-calm-hub-readonly.yml (makes it consistent with readonly-native), or
  • drop calm-hub-ui/** from this doc row if the omission is deliberate.

I'd lean towards the first for parity with the readonly-native workflow, but flagging it in case the trigger set is intentionally narrower here.

@jpgough-ms jpgough-ms marked this pull request as draft June 16, 2026 12:21
@jpgough-ms

Copy link
Copy Markdown
Member Author

Moving back to draft as this PR needs to take into account the new structure

@jpgough-ms jpgough-ms marked this pull request as ready for review June 20, 2026 09:14
ofligit and others added 13 commits June 20, 2026 10:15
…ck diagram widget (finos#2614)

* feat(calm-widgets): add an option to display the relationship's unique-id as the edge-label

* Quarkus 3.34.2 => 3.34.7 (finos#2608)

* chore(calm-hub): Quarkus 3.34.2 => 3.34.3

* chore(calm-hub): Quarkus 3.34.3 => 3.34.7

* chore(calm-hub): bump Netty to 4.1.134.Final

* chore(calm-hub): bump Netty to 4.1.135.Final

---------

Co-authored-by: jpgough-ms <152306432+jpgough-ms@users.noreply.github.com>

* fix(calm-hub): pin MCP server to 1.12.1 to restore native image builds (finos#2618)

quarkus-mcp-server-bom:3.34.7 (added in PR finos#2608) resolves all MCP
artifacts to 1.10.5, a downgrade from the previously pinned 1.12.0.
Version 1.10.5 predates the native-image fix added in 1.12.0
(quarkiverse/quarkus-mcp-server#684/finos#685: fix elicitation and sampling
in native image), causing both native CI workflows to fail at Quarkus
augmentation.

Add explicit dependencyManagement overrides in calm-hub/pom.xml pinning
all five MCP runtime and deployment artifacts to 1.12.1, overriding the
1.10.5 resolved by the platform BOM.

Verified: both build-native-image.sh --no-docker and
build-readonly-native-image.sh --no-docker produce BUILD SUCCESS with a
220MB native binary.

* fix(calm-hub): make the default profile secure and introduce no-auth profile (finos#2629)

* fix(calm-hub): make the default profile secure and introduce no-auth profile for local dev mode

* fix(calm-hub): coverage

* fix(calm-hub): integration test fix

* Native build issues (finos#2619)

* fix(calm-hub): pin MCP server to 1.12.1 to restore native image builds

quarkus-mcp-server-bom:3.34.7 (added in PR finos#2608) resolves all MCP
artifacts to 1.10.5, a downgrade from the previously pinned 1.12.0.
Version 1.10.5 predates the native-image fix added in 1.12.0
(quarkiverse/quarkus-mcp-server#684/finos#685: fix elicitation and sampling
in native image), causing both native CI workflows to fail at Quarkus
augmentation.

Add explicit dependencyManagement overrides in calm-hub/pom.xml pinning
all five MCP runtime and deployment artifacts to 1.12.1, overriding the
1.10.5 resolved by the platform BOM.

Verified: both build-native-image.sh --no-docker and
build-readonly-native-image.sh --no-docker produce BUILD SUCCESS with a
220MB native binary.

* fix(calm-hub): remove Netty version override to fix native image on x86_64

Netty 4.1.135.Final (overridden in PR finos#2608) registers
io.netty.handler.codec.compression.BrotliDecoder for link-at-build-time
in netty-codec's native-image config. On linux/x86_64 (CI), brotli4j
native libs are not on the classpath, causing a fatal unresolved method
error during native image analysis.

Quarkus 3.34.7 already manages Netty at 4.1.132.Final, which patches
CVE-2025-58057, CVE-2026-33870, and CVE-2026-33871 (all affecting
<=4.1.131.Final). The 4.1.135.Final override is unnecessary and breaks
native image compilation on x86_64 CI runners.

* fix(calm-hub): remove duplicated MCP dependencyManagement block

The five io.quarkiverse.mcp version overrides (and their comment) were
accidentally duplicated in the dependencyManagement section. Remove the
second identical copy, leaving one set pinning all MCP artifacts to 1.12.1.

* fix(calm-hub): fix missing validation annotations (finos#2630)

* feat(calm-hub): nest mapping controller under /mappings and add link-… (finos#2633)

* feat(calm-hub): nest mapping controller under /mappings and add link-to-existing endpoint

Rename Front Controller feature to Mapping Controller and nest its REST
resources under /mappings/ so a customId cannot shadow reserved path
segments. Add a PUT endpoint to map a customId to an existing resource,
validating that the target exists within the same namespace.

Closes finos#2628

* fix(calm-hub): apply @Valid @NotNull to linkExistingResource request body

Address Will's review feedback on PR finos#2633: replace the raw String requestBody
parameter and manual JSON parsing / null checks in linkExistingResource with a
typed, bean-validated MappingLinkRequest DTO, matching the convention used by
all other resource endpoints (PatternResource, NamespaceResource, etc.).

---------

Co-authored-by: Mark Scott <markscot@morganstanley.com>
Co-authored-by: jpgough-ms <152306432+jpgough-ms@users.noreply.github.com>
Co-authored-by: Will Osborne <will.osborne@morganstanley.com>
Co-authored-by: Matthew Bain <66839492+rocketstack-matt@users.noreply.github.com>
* feat(calm-hub): WIP on User Facing API

* feat(calm-hub): introduce /calm user-facing API with CalmDocumentParser service

- Add CalmDocumentParser @ApplicationScoped service extracting all $id
  parsing, validation and rewriting logic from MappingControllerResource
- Add unit tests (TestCalmDocumentParserShould) covering parseCanonicalId,
  parseDomainControlId, resolveAndVerify, stripId/rewriteId, getLatestVersion,
  parseTypePlural, extractIdFromJson and domainPrefix
- Enforce write-scope on POST /calm and PUT /calm via CalmHubPermissionChecker
- Reconcile integration tests (Mongo + Nitrite) to versioned $id contract
- Add PermittedScopesIntegration tests for 403 on read-only user writes
- Add @beforeeach canWrite stub to three controller test classes
- Add ControlConfigDetail domain class; update control store and resources

* refactor(calm-hub): explicit versions only, preserve $id, require title on create

- Remove versionless/latest GET endpoint; only explicit versioned GET supported
- Persist documents with $id intact (no longer stripped before write)
- Read title (required) and description (optional) from document body on create
- Remove stripId and getLatestVersion from CalmDocumentParser
- Add extractStringField to CalmDocumentParser
- Return 400 if title is absent or blank on new resource creation
- Update unit, controller and integration tests accordingly

* test(calm-hub): cover MappingControllerResource missing branches to fix jacoco

Add tests for uncovered lines in MappingControllerResource to bring line
coverage from 0.76 to 0.98, above the required 0.90 threshold:

- Blank/invalid JSON body guards (POST /calm, POST /calm/namespaces/..., POST /calm/domains/.../requirement, POST /calm/domains/.../configurations)
- Permission-denied (403) branches for namespace and domain writes via POST /calm
- Invalid resource type (400) branches on POST, GET versions, and GET specific version
- NamespaceNotFoundException catch blocks on create, list-versions, versioned-path POST, and GET version
- createDomain reserved GLOBAL name guard (400)
- Domain/control/config error branches for all GET endpoints:
  DomainNotFoundException, ControlNotFoundException, ControlConfigurationNotFoundException,
  ControlRequirementVersionNotFoundException, ControlConfigurationVersionNotFoundException
- handleControlRequirementPost: blank body, 409 version-exists, 404 control-not-found
- handleControlConfigurationPost: blank body, missing $id, $id mismatch, non-1.0.0 first version, 409 version-exists, 404 config-not-found, 404 domain-not-found, 404 control-not-found
- PUT /calm: blank body, invalid JSON, 403 forbidden namespace, 404 namespace-not-found in store call, 500 unexpected error

* fix(calm-hub): Bug in tests

* fix(calm-hub): strip verified $id before persisting /calm documents

The /calm user-facing API persisted the document's $id field unchanged.
MongoDB reserves top-level $-prefixed field names (a bare $id is only
valid inside a DBRef), so every create/version write rejected the
document with write error code 55, surfacing as 400/500. NitriteDB has
no such rule, which is why only the Mongo paths failed.

The canonical $id is already verified against the path on write and
re-derived on read via CalmDocumentParser.rewriteId, so it must not be
stored. Add CalmDocumentParser.stripId and apply it at every /calm
persistence boundary (namespace create/version, control requirement and
configuration, and PUT). The contract is now: verify $id matches the
canonical target, reject with 400 if not, otherwise strip and store.

Tests:
- Flip the unit assertion to require the store receive the document
  without $id; add stripId unit cases.
- Update the mapping ITs to the versioned contract (no versionless POST;
  control payload carries its type).
- Migrate the Search, ProxyAuth and concurrency control tests off the
  removed POST /calm/domains/{domain}/controls shape to the name-based
  versioned endpoint.
- Seed flowStoreCounter in MongoSetup so concurrent first-flow creation
  no longer races on counter initialisation (E11000).

* fix(calm-hub): apply copilot PR review comments from finos#2653

- Migrate all storage API client paths from /calm/namespaces to
  /api/calm/namespaces in CalmHubClient and its spec
- Remove debug console.debug logging of request params and
  requirementJson payload from pushControlRequirement
- Correct application.properties comment: base-url defaults to
  http://localhost:8080 when unset, not skip verification
- Fix Drawer slug decorator fetch: resolve slug to numericId via
  fetchMappings before building /api/calm/namespaces/{ns}/architectures/
  {numericId}/versions/{v} target instead of the broken slug path

* refactor(calm-hub): address Will Osborne PR review comments on MappingControllerResource

- Extract MappingControllerService (@ApplicationScoped) containing all
  business logic: store interactions, createOrAddVersion, updateVersioned
  Resource, getVersionsForMapping, getResourceJsonForVersion, control
  requirement/configuration handling, resolveControlId/resolveConfigId
- MappingControllerResource reduced from ~1250 to ~430 lines; now a thin
  HTTP layer responsible only for JAX-RS wiring, permission checks, and
  exception-to-Response mapping
- Replace all inline @jakarta.validation.constraints.Pattern FQNs with
  an import and shorthand @pattern (covers ~12 sites)
- Remove duplicated getMapping->createOrAddVersion block from both
  createResourceFromDocument and handlePost; both now delegate to
  service.createOrAddVersion()

Verified: 1945/1945 unit tests pass, 490/490 integration tests pass

---------

Co-authored-by: Matthew Bain <66839492+rocketstack-matt@users.noreply.github.com>
…nos#2500)

* chore(calm-models): Add string diff packages and types

* feat(calm-models): Add ADR diff engine and tests

* chore(shared): Update types for successful compilation

* chore(calm-hub-ui): Update types for successful compilation

* docs(calm-models): Improve docstring for diffArchitectures params

* chore(calm-models): Export nodes and relationships diff result, add doc comment

* chore: re-sync package-lock.json

* fix(calm-models): final fixes
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Centralises patched versions via root overrides (and the advent-of-calm
website overrides for its standalone lockfile):
- tmp ^0.2.6 -> ^0.2.7 (override too loose, permitted vulnerable 0.2.6)
- esbuild -> ^0.28.1 (new root + advent-of-calm/website override)
- joi -> ^17.13.4 (new root override)

Also removes the @vscode/vsce minimatch override. baa5716 intended that
pin only for minimatch 3.x consumers, but @vscode/vsce requires minimatch
^10.2.2; forcing 3.1.x broke "vsce package" (minimatch_1.minimatch is not
a function) on a clean lockfile regeneration. vsce now resolves the
already-patched minimatch 10.2.5.

Bumps calm-hub-ui @vitejs/plugin-react ^4.3.4 -> ^5.0.0. Required to
regenerate the lockfile cleanly: finos#2657 bumped vite to 8 but plugin-react
4.x only peers vite <=7, so a clean install ERESOLVEs. plugin-react 5.2.0
(already hoisted at root) supports vite 8 and dedupes to one copy.

Resolves: GHSA-7c78-jf6q-g5cm, GHSA-gv7w-rqvm-qjhr, GHSA-g7r4-m6w7-qqqr, GHSA-q7cg-457f-vx79
* feat(calm-hub): allow * as reserved public-access username

Update USERNAME_REGEX to accept the literal * character as a valid
username, representing public/anyone access. Prevents collision with
real OIDC identities. Tests verify * is accepted and ** is rejected.

* feat(calm-hub): add getGrantsForUser to UserAccessStore

New store method returns a user's own grants plus * (public) grants
in a single query, avoiding two round-trips per permission check.
Returns an empty list rather than throwing when no grants exist.
Implemented for both Mongo and Nitrite backends.

* feat(calm-hub): implement hierarchical namespace permission checks

Replace flat exact-match logic with ancestor-chain evaluation:
- READ: AND-based — every ancestor level must have a grant (user or *)
- WRITE/ADMIN: OR-based — any ancestor grant is sufficient

Introduces ancestorChain() helper, switches hasNamespaceAccess to use
getGrantsForUser for a single store round-trip. Domain checks and
global admin are unchanged. Corrects a logic error in the docs example
(mark cannot read a child namespace without a grant at that level).

* feat(calm-hub): introduce NamespaceService with default public read grant

NamespaceResource now delegates all namespace operations through
NamespaceService, removing direct store access from the resource.
On namespace creation the service inserts a * read grant automatically,
making every new namespace publicly readable by default.

* feat(calm-hub): add NamespaceMigrationService to backfill * read grants

On startup, inserts a * read grant for any namespace that has no grants
at all, preserving public visibility after the hierarchical model is
deployed. Namespaces with existing grants (even user-specific ones) are
left untouched — the admin configured them intentionally and backfilling
would grant unintended additional access. Operation is idempotent.

* feat(calm-hub): apply hierarchical AND rule to getReadableNamespaces

Switch from getUserAccessForUsername (flat, misses * grants) to
getGrantsForUser (user + * grants in one call), then apply the same
AND ancestor-chain check as canRead: a namespace is included only if
every level in its chain has a READ-sufficient grant. Guarantees search
results never include namespaces that would return 403 on click-through.

* docs(calm-hub): document hierarchical entitlement model

Update PERMISSIONS.md as the internal developer reference covering the
AND/OR ancestor-chain rules, key classes, and store method distinction.
Add an Access Control section to calm-hub.md linking to the new
calm-hub-entitlements.md user-facing page.

* fix(calm-hub): add * read grants and fix counter in mongo seed data

The MongoDB init script bypasses NamespaceService (direct db.namespaces
insert), so the auto-inserted * read grant from NamespaceService never ran.
NamespaceMigrationService then skips finos/workshop/traderx at startup
because they already have named-user grants (demo/demo_admin).

Add explicit * read grants (IDs 7-10) for all four seeded namespaces so
the seed matches the default-open behaviour of NamespaceService, and
bump userAccessStoreCounter from 6 to 11 (was off-by-one: 6 docs with
IDs 1-6 existed, but counter was initialised to 6 instead of 7).

* fix(calm-hub): skip namespace migration in test mode via LaunchMode check

NamespaceMigrationService.onStart() returns immediately when
LaunchMode.current() == TEST, preventing it from attempting a MongoDB
connection during @QuarkusTest and @testprofile startups where DevServices
does not re-patch the connection string after a profile restart.

Pure Mockito unit tests are unaffected: LaunchMode.current() returns NORMAL
when no Quarkus context is active, so all nine migration unit tests
continue to exercise the full migration path.

* test(calm-hub): mock UserAccessStore in TestSecurityResponseHeadersShould

createNamespace() now also inserts a * read grant via UserAccessStore.
The POST /calm/namespaces test in TestSecurityResponseHeadersShould was
not mocking UserAccessStore, so the real MongoDB implementation timed out
in CI where MongoDB is not available at localhost:27017.

* fix(calm-hub): address Copilot PR review comments

- NamespaceMigrationService Javadoc: clarify that backfill is skipped
  when any grant exists (wildcard or named-user), not just wildcard grants
- CalmHubPermissionChecker: downgrade per-request auth outcome logs from
  INFO/WARN to DEBUG to avoid flooding production logs
- UserAccessValidator.getReadableNamespaces(): return Optional<Set<String>>
  where Optional.empty() signals "all namespaces" (no filter). Short-circuit
  to Optional.empty() when calm.auth.allow-public-read=true or the user
  holds a GLOBAL admin grant, so search results match canRead() in all cases
- SearchTools: unwrap the Optional directly from getReadableNamespaces()
- Tests: use containsInAnyOrder for order-independent assertions in
  getGrantsForUser tests; add bypass-case coverage for UserAccessValidator

Rejected: O(ancestors×grants) optimisation (premature at realistic scale)

* fix(calm-hub): update SearchResource and test to use Optional<Set<String>> return type

getReadableNamespaces() now returns Optional<Set<String>> to distinguish
unconstrained access (empty Optional) from no access (Optional of empty set).
SearchResource and TestSearchResourceFilteringShould updated to match.
…date (finos#2663)

Bumps the npm_and_yarn group with 1 update in the /calm-plugins/vscode/screenshots directory: [js-yaml](https://github.com/nodeca/js-yaml).


Updates `js-yaml` from 4.1.1 to 4.2.0
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/commits)

Updates `js-yaml` from 4.1.1 to 4.2.0
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/commits)

Updates `js-yaml` from 4.1.1 to 4.2.0
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/commits)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.2.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: js-yaml
  dependency-version: 4.2.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: js-yaml
  dependency-version: 4.2.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…inos#2667)

Consolidate the CALM Studio docs into the main Working with CALM section
so all CALM tools sit together, and remove the standalone CALM Studio
entry from the top navigation (it mixed user-facing and developer docs).

- Add a single, tool-focused CALM Studio page under Working with CALM
- Remove the CALM Studio top-nav item and its dedicated sidebar
- Drop the CALM Studio developer-guide and ADR pages
- Move the Architecture Discovery Skill tutorial from Advanced to
  Practitioner (the Advanced category is now empty and removed)
- Alphabetise the Working with CALM navigation and index list
…ests

- ReadOnlyRequestFilter now intercepts mutating verbs on both /calm/* and
  /api/calm/* paths, ensuring the read-only images block writes on the full
  API surface (user-facing mapping layer + numeric-ID storage layer)
- Added 12 new unit-test cases (via @valuesource ParameterizedTest) covering
  /api/calm/* mutating-reject, read-allow, and with/without leading-slash scenarios
- smoke-test.sh rewritten for the post-refactor API surface:
  - Readonly: asserts 405 on POST/PUT/DELETE to both /api/calm/namespaces and /calm
  - Readwrite: creates namespace via /api/calm/namespaces (201), creates architecture
    via POST /calm/namespaces/{ns}/architectures/{name}/versions/{v} with $id body,
    lists/retrieves via /calm/namespaces/{ns}/architectures/{name}/versions,
    asserts PUT /calm → 403 (allow.put.operations=false)

Claude-Session: https://claude.ai/code/session_013pc5dc4YRfqsWEqEJ81UUb
init-nitrite.sh and seed-readonly.sh still used the pre-refactor /calm/namespaces
and /calm/domains paths for namespace/domain/resource CRUD; those moved to
/api/calm/namespaces and /api/calm/domains. /calm/schemas is unchanged.

Changes:
- init-nitrite.sh: all POST/GET for namespaces, architectures, patterns, flows,
  standards, timelines, user-access, domains, and controls updated to /api/calm/...
- seed-readonly.sh: verification curl (line 90) updated to /api/calm/namespaces

Claude-Session: https://claude.ai/code/session_013pc5dc4YRfqsWEqEJ81UUb
…ava.time serialization

Two bugs in the native read-only Docker image:

1. Dockerfile.readonly-native used `--chmod=0444` on the COPY that bakes
   the NitriteDB file into the final distroless image. BuildKit applies
   --chmod to every item in the COPY, including parent directories created
   on-the-fly. This left /deployments/data/ as dr--r--r-- (no execute bit),
   making the directory non-traversable and causing `Files.exists()` to
   return false even though the file was present. Fix: chmod the db file
   to 0444 in the seed stage (RUN chmod) so the COPY in the final stage
   can omit --chmod, letting Docker create the directory with the default
   0755 mode while the file inherits the 0444 source permissions.

2. UserAccess domain objects (created by NamespaceMigrationService at startup)
   have LocalDateTime fields. Java's ObjectOutputStream serialises these via
   java.time.Ser, the JDK-internal serialisation proxy for all java.time
   types. This class was not registered in serialization-config.json, so
   the native binary threw ClassNotFoundException: java.time.Ser when the
   NitriteDB MVStore tried to deserialise stored documents. Fix: add
   java.time.Ser, LocalDateTime, LocalDate, and LocalTime to the serialisation
   configuration (baked into the native binary at compile time by Mandrel via
   -H:SerializationConfigurationResources).

Claude-Session: https://claude.ai/code/session_013pc5dc4YRfqsWEqEJ81UUb
@linux-foundation-easycla

Copy link
Copy Markdown

CLA Missing ID

One or more co-authors of this pull request were not found. You must specify co-authors in commit message trailer via:

Co-authored-by: name <email>

Supported Co-authored-by: formats include:

  1. Anything <id+login@users.noreply.github.com> - it will locate your GitHub user by id part.
  2. Anything <login@users.noreply.github.com> - it will locate your GitHub user by login part.
  3. Anything <public-email> - it will locate your GitHub user by public-email part. Note that this email must be made public on Github.
  4. Anything <other-email> - it will locate your GitHub user by other-email part but only if that email was used before for any other CLA as a main commit author.
  5. login <any-valid-email> - it will locate your GitHub user by login part, note that login part must be at least 3 characters long.

Alternatively, if the co-author should not be included, remove the Co-authored-by: line from the commit message.

Please update your commit message(s) by doing git commit --amend and then git push [--force] and then request re-running CLA check via commenting on this pull request:

/easycla

@github-actions github-actions Bot added cli Affects `cli` code shared config labels Jun 20, 2026
@jpgough-ms jpgough-ms closed this Jun 20, 2026
jpgough-ms added a commit to jpgough-ms/architecture-as-code that referenced this pull request Jun 20, 2026
Addresses Copilot review on PR finos#2615: calm-hub/pom.xml overrides io.quarkiverse.mcp:quarkus-mcp-server-http to 1.12.1, but two docs still cited 1.12.0. Bring them in line so contributors land on the right release notes / native-image fix level.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

calm-hub Affects `calm-hub` calm-hub-ui Affects `calm-hub-ui` cli Affects `cli` code config docs Improvements of additions to documentation shared

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants