Skip to content

LNK-4711: Informative validation of Measure/Validation Artifacts - #1374

Merged
seanmcilvenna merged 10 commits into
devfrom
LNK-4711
Jan 29, 2026
Merged

LNK-4711: Informative validation of Measure/Validation Artifacts#1374
seanmcilvenna merged 10 commits into
devfrom
LNK-4711

Conversation

@seanmcilvenna

@seanmcilvenna seanmcilvenna commented Jan 15, 2026

Copy link
Copy Markdown
Contributor

🛠️ Description of Changes

  • New backend operation to return information about a measure's related artifacts
  • Modifications to UI to allow user to click on a measure and see the info about the measure's related artifacts.
  • New backend operation for getting a package's terminology dependencies, and checking if those dependencies are loaded
  • Modifications to Implementation Guides configuration to visualize a package's terminology dependencies

🧪 Testing Performed

Built and ran in docker-compose. Viewed the screen with its changes and clicked around to make sure it's functioning as expected. Screen looks good.

🧑‍🔬 Unit Testing

  • I have written or updated unit tests to cover my changes

📓 Documentation Updated

N/A

Summary by CodeRabbit

Release Notes

New Features

  • Added a related artifacts view that displays dependencies and library metadata associated with each measure definition.
  • Measure IDs in the configuration form are now clickable, opening an interactive modal showing artifact details including name, version, URL, and availability status.
  • New backend API endpoint retrieves related artifact information for measures.

Tests

  • Added comprehensive test coverage for related artifacts retrieval with edge-case handling.

✏️ Tip: You can customize this high-level summary in your review settings.

… artifacts

Modifications to UI to allow user to click on a measure and see the info about the measure's related artifacts.
@coderabbitai

coderabbitai Bot commented Jan 15, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
📝 Walkthrough

Walkthrough

This PR introduces a feature enabling system administrators to view measure dependencies and their availability within the system. It adds a backend REST endpoint that inspects measure bundles to identify related artifacts, returning artifact metadata with version and library information, complemented by a frontend modal component to display these results.

Changes

Cohort / File(s) Summary
Backend Service Layer
Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/services/MeasureValidationService.java
New Spring service implementing core logic to parse measure bundles and extract related artifacts. Identifies dependencies (DEPENDSON type), filters out CQF-prefixed URLs, maps artifact versions, and tracks whether each artifact is found in the bundle. Includes error handling for missing measures and bundles.
Backend Model
Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/models/RelatedArtifactInfo.java
New data model class with Lombok annotations. Holds artifact metadata: name, url, version, found flag, and a map of associated libraries. Serves as response payload for the REST endpoint.
Backend Controller
Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/controllers/MeasureDefinitionController.java
Adds GET /{id}/relatedArtifact endpoint and wires MeasureValidationService dependency. Delegates to service for artifact resolution.
Backend Tests
Java/measureeval/src/test/java/com/lantanagroup/link/measureeval/services/MeasureValidationServiceTest.java
Comprehensive test suite covering success path (multi-library dependencies, mixed found/not-found artifacts), error scenarios (missing measure, missing bundle), and edge cases (non-metadata resources, CQF URL filtering).
Frontend Modal Component
Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.ts, related-artifacts-modal.component.html, related-artifacts-modal.component.scss
New standalone Angular modal component that fetches and displays related artifacts in a Material data table. Shows name, version, URL, and found status with visual indicators (icons and styling). Includes loading state and library tooltip support.
Frontend Service Integration
Web/Admin.UI/src/app/services/gateway/measure-definition/measure.service.ts
Adds getRelatedArtifacts(id) method to MeasureDefinitionService, calling the new backend endpoint with error handling.
Frontend Interface
Web/Admin.UI/src/app/interfaces/measure-definition/related-artifact.interface.ts
Exports IRelatedArtifact interface defining the structure for frontend artifact data.
Frontend Form Component
Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.ts, measure-def-config-form.component.html
Integrates modal trigger: converts measure ID cells from static text to clickable buttons that open the related artifacts modal via MatDialog. Updates component constructor to inject MatDialog.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant AdminUI as Admin UI
    participant Modal as Related Artifacts Modal
    participant Service as Measure Definition Service
    participant Controller as MeasureDefinitionController
    participant Validation as MeasureValidationService
    participant Repo as Repository
    participant DB as Database

    User->>AdminUI: Click measure ID button
    AdminUI->>Modal: Open modal with measure ID
    activate Modal
    Modal->>Service: getRelatedArtifacts(id)
    activate Service
    Service->>Controller: GET /{id}/relatedArtifact
    activate Controller
    Controller->>Validation: getRelatedArtifacts(id)
    activate Validation
    Validation->>Repo: findById(id)
    Repo->>DB: Query measure definition
    DB-->>Repo: Return measure with bundle
    Repo-->>Validation: MeasureDefinition
    Validation->>Validation: Parse bundle, extract<br/>related artifacts,<br/>determine found status
    Validation-->>Controller: List<RelatedArtifactInfo>
    deactivate Validation
    Controller-->>Service: HTTP 200 + artifacts
    deactivate Controller
    Service-->>Modal: Observable<IRelatedArtifact[]>
    deactivate Service
    Modal->>Modal: Update artifacts list,<br/>set loading = false
    deactivate Modal
    Modal-->>User: Display artifacts table
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • sdmcgeown
  • smailliwcs

Poem

🐰 A rabbit's ode to artifact sight:

Bundle dependencies, now shown in light,
Which artifacts dance, which ones are missing,
Admin's concerns get quick dismissing.
Hop-hop validates the measure's might! 🎯

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description covers the required sections with sufficient detail: changes, testing performed, unit testing confirmation, and documentation status.
Linked Issues check ✅ Passed The implementation fully addresses LNK-4711 requirements: backend service returns related artifacts, UI displays artifact details, and found flag indicates artifact availability.
Out of Scope Changes check ✅ Passed All code changes are directly related to implementing the measure artifact validation feature with no unrelated modifications.
Title check ✅ Passed The title clearly and specifically describes the main change: adding validation/information display for measure artifacts, matching the core feature of this PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.ts (1)

35-38: Duplicate MatIconModule import.

MatIconModule is imported twice in the imports array (lines 35 and 38).

Proposed fix
   imports: [
     MatIconModule,
     MatFormFieldModule,
     MatInputModule,
-    MatIconModule,
     MatChipsModule,
🤖 Fix all issues with AI agents
In
`@Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/controllers/MeasureDefinitionController.java`:
- Around line 167-172: Add the GET /{id}/relatedArtifact path to the OpenAPI
spec in docs/domains/Report/services/MeasureEvalService/openapi.yml: mirror the
style of other measure-definition paths and document OperationId (e.g.,
getRelatedArtifacts), summary "Get related artifacts for a measure definition",
a path parameter "id" (string, required) and the 200 response returning an array
of the RelatedArtifactInfo schema (ensure RelatedArtifactInfo model/schema is
defined or referenced exactly as used by the
MeasureDefinitionController.getRelatedArtifacts method), plus appropriate tags
("Measure Definitions") and example/description fields consistent with existing
endpoints.

In
`@Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.html`:
- Around line 42-44: The template uses an anchor tag for a click-only action
which is semantically incorrect; replace the <a mat-button color="primary"
(click)="openRelatedArtifactsModal(element)">{{ element.id }}</a> with a <button
mat-button> variant so it is keyboard and screen-reader accessible and still
calls openRelatedArtifactsModal(element) (keep the same click handler and
displayed {{ element.id }}). Ensure any CSS or styling targeting the anchor is
updated to target the button if needed.
🧹 Nitpick comments (7)
Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/services/MeasureValidationService.java (1)

119-122: Simplify the count operation.

The mapToInt(info -> 1).sum() pattern can be replaced with the more idiomatic .count() method.

♻️ Suggested simplification
-        int notFoundCount = relatedArtifactInfos.stream()
-                .filter(info -> !info.isFound())
-                .mapToInt(info -> 1)
-                .sum();
+        long notFoundCount = relatedArtifactInfos.stream()
+                .filter(info -> !info.isFound())
+                .count();
Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.scss (2)

24-26: ::ng-deep is deprecated in Angular.

While ::ng-deep still works, it has been deprecated. Consider using global styles in a theme file or the component's encapsulation: ViewEncapsulation.None for tooltip styling that needs to pierce shadow DOM boundaries.


15-18: Consider using Angular Material theme variable for consistency.

The hardcoded color #f44336 works but using a theme variable like mat.get-color-from-palette($warn-palette) would ensure consistency with the application's theme and simplify future theme changes.

Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/controllers/MeasureDefinitionController.java (2)

167-172: Missing user tracing and authentication principal for consistency.

Other endpoints in this controller capture the @AuthenticationPrincipal PrincipalUser and set span attributes for user tracing. This endpoint lacks that pattern, which may create gaps in observability.

Proposed fix
 `@GetMapping`("/{id}/relatedArtifact")
 `@Operation`(summary = "Get related artifacts for a measure definition", tags = {"Measure Definitions"})
 `@Parameter`(name = "id", description = "The ID of the measure definition", required = true)
-public List<RelatedArtifactInfo> getRelatedArtifacts(`@PathVariable` String id) {
+public List<RelatedArtifactInfo> getRelatedArtifacts(`@AuthenticationPrincipal` PrincipalUser user, `@PathVariable` String id) {
+    if (user != null) {
+        Span currentSpan = Span.current();
+        currentSpan.setAttribute("user", user.getEmailAddress());
+    }
     return validationService.getRelatedArtifacts(id);
 }

167-167: Consider using plural form relatedArtifacts in the endpoint path.

The endpoint returns List<RelatedArtifactInfo>, so using plural /relatedArtifacts would be more consistent with REST conventions for collection resources.

Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.html (1)

7-35: Consider adding an empty state message when no related artifacts are found.

If relatedArtifacts is an empty array, the table will render with just headers and no rows, which may confuse users. Adding an empty state message would improve UX.

Proposed enhancement
   <table mat-table [dataSource]="relatedArtifacts" *ngIf="!loading" class="mat-elevation-z8">
     <!-- ... existing columns ... -->
     <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
     <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+    <tr class="mat-row" *matNoDataRow>
+      <td class="mat-cell" [attr.colspan]="displayedColumns.length">No related artifacts found.</td>
+    </tr>
   </table>
Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.ts (1)

37-47: Add error state handling to provide user feedback on failure.

The error handler silently sets loading = false without storing or displaying an error message. Users will see an empty table with no indication that a failure occurred, making it impossible to distinguish between "no artifacts" and "failed to load."

Consider adding an errorMessage property and displaying it in the template:

♻️ Suggested improvement
 export class RelatedArtifactsModalComponent implements OnInit {
   relatedArtifacts: IRelatedArtifact[] = [];
   displayedColumns: string[] = ['name', 'version', 'url', 'found'];
   loading = true;
+  errorMessage: string | null = null;

   constructor(
     `@Inject`(MAT_DIALOG_DATA) public data: { id: string },
     private measureDefinitionService: MeasureDefinitionService
   ) {}

   ngOnInit(): void {
     this.measureDefinitionService.getRelatedArtifacts(this.data.id).subscribe({
       next: (artifacts) => {
         this.relatedArtifacts = artifacts;
         this.loading = false;
       },
-      error: () => {
+      error: (err) => {
         this.loading = false;
+        this.errorMessage = 'Failed to load related artifacts. Please try again.';
+        console.error('Error loading related artifacts:', err);
       }
     });
   }

Then display the error in the template when errorMessage is set.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d9208d6 and e668ea4.

📒 Files selected for processing (11)
  • Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/controllers/MeasureDefinitionController.java
  • Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/models/RelatedArtifactInfo.java
  • Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/services/MeasureValidationService.java
  • Java/measureeval/src/test/java/com/lantanagroup/link/measureeval/services/MeasureValidationServiceTest.java
  • Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.html
  • Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.ts
  • Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.html
  • Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.scss
  • Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.ts
  • Web/Admin.UI/src/app/interfaces/measure-definition/related-artifact.interface.ts
  • Web/Admin.UI/src/app/services/gateway/measure-definition/measure.service.ts
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

**: Pull requests that have "TECH_DEBT" in the title should only contain changes related to typos, unused code, linter/IDE suggestions, swagger specification updates,
and logging improvements. These TECH_DEBT PRs must not affect core functionality. All PRs that are not considered technical debt must include information on what
testing was performed in the description of the PR. If it does not, ask the author to provide details on what testing was performed.
When reviewing code, suggest unit tests using XUnit in the following scenarios:

  • If/Else or Switch/Case blocks are introduced or modified — ensure each branch has a corresponding unit test.
  • Logic that depends on service or interface configuration — suggest tests to validate different implementations are correctly resolved.
  • No network activity (HTTP calls, sockets, etc.) should appear in unit tests. Recommend using mocks (via Moq) for any external communication.
    Large unit tests should be avoided; keeping unit tests small and focused on targeted business logic (i.e. string sanitization)

**: Pull requests that have DOCS in the title should only contain changes related to documentation within the /docs folder or in .md files through-out the code-base. The description
of the PR should specify what documentation was updated. Documentation updates should use EventCatalog.dev structure, where service-specific functionality should be described
in the service's index.mdx (i.e. /services/XXX/index.mdx or /domains/XXX/services/YYY/index.mdx). Configurations that are shared by multiple services should be
reflected in the /docs/docs/config files.

Files:

  • Web/Admin.UI/src/app/interfaces/measure-definition/related-artifact.interface.ts
  • Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.html
  • Web/Admin.UI/src/app/services/gateway/measure-definition/measure.service.ts
  • Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/models/RelatedArtifactInfo.java
  • Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.scss
  • Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.ts
  • Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.ts
  • Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/services/MeasureValidationService.java
  • Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/controllers/MeasureDefinitionController.java
  • Java/measureeval/src/test/java/com/lantanagroup/link/measureeval/services/MeasureValidationServiceTest.java
  • Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.html
🧠 Learnings (4)
📓 Common learnings
Learnt from: sdmcgeown
Repo: lantanagroup/link-cloud PR: 0
File: :0-0
Timestamp: 2025-07-24T17:49:23.117Z
Learning: PR `#1004` in the Link Cloud project introduced comprehensive normalization operation testing functionality including a new test operation dialog, JSON validation, resource type validation, and real-time testing capabilities that require documentation updates across multiple files in the docs folder.
Learnt from: arianamihailescu
Repo: lantanagroup/link-cloud PR: 0
File: :0-0
Timestamp: 2025-08-13T17:27:27.383Z
Learning: The MeasureEvalService in the Link Cloud project has comprehensive OpenAPI documentation at docs/domains/Report/services/MeasureEvalService/openapi.yml that needs to be updated when API endpoints change, particularly for measure-definition endpoints.
Learnt from: seanmcilvenna
Repo: lantanagroup/link-cloud PR: 0
File: :0-0
Timestamp: 2025-07-30T22:50:26.140Z
Learning: PR `#1030` in the Link Cloud project introduced Category and Issue Retrieval Operations to the Validation Service, including new ResultService for business logic separation, CategoryController and ResultController endpoints, and models for CategorySummaryModel and CategoryIssueModel with uncategorized issue handling.
📚 Learning: 2025-05-13T19:11:06.305Z
Learnt from: amphillipsLGC
Repo: lantanagroup/link-cloud PR: 836
File: Web/Admin.UI/src/app/components/audit/audit-dashboard/audit-dashboard.component.ts:129-133
Timestamp: 2025-05-13T19:11:06.305Z
Learning: In this Angular application, error handling for HTTP requests is implemented at the service level using a centralized ErrorHandlingService. Components don't need to implement their own error handling when calling service methods as errors are already handled by the service through RxJS catchError operator.

Applied to files:

  • Web/Admin.UI/src/app/services/gateway/measure-definition/measure.service.ts
📚 Learning: 2025-08-13T17:27:27.383Z
Learnt from: arianamihailescu
Repo: lantanagroup/link-cloud PR: 0
File: :0-0
Timestamp: 2025-08-13T17:27:27.383Z
Learning: The MeasureEvalService in the Link Cloud project has comprehensive OpenAPI documentation at docs/domains/Report/services/MeasureEvalService/openapi.yml that needs to be updated when API endpoints change, particularly for measure-definition endpoints.

Applied to files:

  • Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/services/MeasureValidationService.java
  • Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/controllers/MeasureDefinitionController.java
  • Java/measureeval/src/test/java/com/lantanagroup/link/measureeval/services/MeasureValidationServiceTest.java
📚 Learning: 2025-08-05T17:06:51.464Z
Learnt from: smailliwcs
Repo: lantanagroup/link-cloud PR: 1042
File: Java/validation/src/main/java/com/lantanagroup/link/validation/services/ReadyForValidationConsumer.java:120-121
Timestamp: 2025-08-05T17:06:51.464Z
Learning: In the Link Cloud validation service, the Report service contract guarantees that a valid response will never contain a null bundle from model.getBundle(), making null checks unnecessary in the ReadyForValidationConsumer.

Applied to files:

  • Java/measureeval/src/test/java/com/lantanagroup/link/measureeval/services/MeasureValidationServiceTest.java
🧬 Code graph analysis (4)
Web/Admin.UI/src/app/services/gateway/measure-definition/measure.service.ts (1)
Web/Admin.UI/src/app/interfaces/measure-definition/related-artifact.interface.ts (1)
  • IRelatedArtifact (1-7)
Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.ts (1)
Web/Admin.UI/src/app/interfaces/measure-definition/measure-definition-config-model.interface.ts (1)
  • IMeasureDefinitionConfigModel (1-5)
Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.ts (2)
Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.ts (1)
  • Component (27-191)
Web/Admin.UI/src/app/interfaces/measure-definition/related-artifact.interface.ts (1)
  • IRelatedArtifact (1-7)
Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/services/MeasureValidationService.java (2)
Web/Admin.UI/src/app/services/gateway/measure-definition/measure.service.ts (1)
  • getRelatedArtifacts (37-43)
Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.ts (1)
  • bundle (90-92)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Smoke Test with Docker Compose
  • GitHub Check: Integration Tests
  • GitHub Check: Unit Tests for DotNet
  • GitHub Check: Analyze (java-kotlin)
  • GitHub Check: Analyze (csharp)
  • GitHub Check: Build Documentation
🔇 Additional comments (13)
Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/models/RelatedArtifactInfo.java (1)

1-17: LGTM!

The model is clean and well-structured. The fields align correctly with the frontend IRelatedArtifact interface, and initializing libraries as a HashMap prevents null pointer exceptions.

Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/services/MeasureValidationService.java (2)

37-127: Consider updating OpenAPI documentation.

Based on learnings, the MeasureEvalService has comprehensive OpenAPI documentation at docs/domains/Report/services/MeasureEvalService/openapi.yml. Since this PR adds a new endpoint (GET /{id}/relatedArtifact), the OpenAPI specification should be updated to document the new endpoint, request/response schemas, and possible error codes (404, 400).


129-142: LGTM!

The helper method correctly extracts canonical URLs with version suffixes for MetadataResource types using idiomatic pattern matching.

Java/measureeval/src/test/java/com/lantanagroup/link/measureeval/services/MeasureValidationServiceTest.java (5)

33-43: LGTM!

Good test coverage for the 404 case with proper exception validation including status code and reason message.


45-59: LGTM!

Properly tests the missing bundle scenario with correct status code and message validation.


61-136: LGTM!

Comprehensive test that covers multiple scenarios including:

  • Artifacts found vs not found in bundle
  • Version extraction from URLs
  • Library associations
  • Ignored CQF URLs and non-DEPENDSON types

The test is thorough without being excessive.


138-168: LGTM!

Good edge case test verifying that non-MetadataResource types (like Patient) are correctly handled and won't be found by canonical URL lookup.


170-208: LGTM!

Clear and focused test for the CQF URL prefix filtering logic. Good coverage of multiple ignored prefixes alongside a non-ignored artifact.

Web/Admin.UI/src/app/services/gateway/measure-definition/measure.service.ts (1)

37-43: LGTM!

The new method follows the established service patterns with proper error handling via the centralized ErrorHandlingService. The endpoint URL correctly matches the backend controller path.

Web/Admin.UI/src/app/interfaces/measure-definition/related-artifact.interface.ts (1)

1-7: LGTM!

The interface correctly mirrors the Java RelatedArtifactInfo model with appropriate TypeScript types and optional modifiers for nullable fields.

Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.html (1)

1-39: LGTM overall!

The modal template is well-structured with appropriate loading state handling, clear visual indicators for found/not-found artifacts, and proper Angular Material component usage.

Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.ts (1)

100-107: LGTM!

The openRelatedArtifactsModal method is clean and follows Angular Material dialog patterns correctly. The dialog dimensions are appropriate for displaying tabular artifact data.

Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.ts (1)

49-52: LGTM! Consider adding a unit test for this helper.

The helper correctly handles the undefined case and formats the libraries for tooltip display. Per coding guidelines, logic like this benefits from unit test coverage to validate the formatting behavior.

Example test cases to consider:

  • undefined input returns empty string
  • Empty object {} returns empty string
  • Single entry formats correctly
  • Multiple entries join with newlines

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@seanmcilvenna seanmcilvenna changed the title LNK-4711: Informative validation of Measure Artifacts LNK-4711: Informative validation of Measure/Validation Artifacts Jan 28, 2026
@coderabbitai

coderabbitai Bot commented Jan 28, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":401,"request":{"method":"PATCH","url":"https://api.github.com/repos/lantanagroup/link-cloud/issues/comments/3756106573","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- walkthrough_start -->\n\n<details>\n<summary>📝 Walkthrough</summary>\n\n## Walkthrough\n\nThis PR introduces a feature enabling system administrators to view measure dependencies and their availability within the system. It adds a backend REST endpoint that inspects measure bundles to identify related artifacts, returning artifact metadata with version and library information, complemented by a frontend modal component to display these results.\n\n## Changes\n\n| Cohort / File(s) | Summary |\n|---|---|\n| **Backend Service Layer** <br> `Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/services/MeasureValidationService.java` | New Spring service implementing core logic to parse measure bundles and extract related artifacts. Identifies dependencies (DEPENDSON type), filters out CQF-prefixed URLs, maps artifact versions, and tracks whether each artifact is found in the bundle. Includes error handling for missing measures and bundles. |\n| **Backend Model** <br> `Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/models/RelatedArtifactInfo.java` | New data model class with Lombok annotations. Holds artifact metadata: name, url, version, found flag, and a map of associated libraries. Serves as response payload for the REST endpoint. |\n| **Backend Controller** <br> `Java/measureeval/src/main/java/com/lantanagroup/link/measureeval/controllers/MeasureDefinitionController.java` | Adds GET /{id}/relatedArtifact endpoint and wires MeasureValidationService dependency. Delegates to service for artifact resolution. |\n| **Backend Tests** <br> `Java/measureeval/src/test/java/com/lantanagroup/link/measureeval/services/MeasureValidationServiceTest.java` | Comprehensive test suite covering success path (multi-library dependencies, mixed found/not-found artifacts), error scenarios (missing measure, missing bundle), and edge cases (non-metadata resources, CQF URL filtering). |\n| **Frontend Modal Component** <br> `Web/Admin.UI/src/app/components/measure-def/related-artifacts-modal/related-artifacts-modal.component.ts`, `related-artifacts-modal.component.html`, `related-artifacts-modal.component.scss` | New standalone Angular modal component that fetches and displays related artifacts in a Material data table. Shows name, version, URL, and found status with visual indicators (icons and styling). Includes loading state and library tooltip support. |\n| **Frontend Service Integration** <br> `Web/Admin.UI/src/app/services/gateway/measure-definition/measure.service.ts` | Adds getRelatedArtifacts(id) method to MeasureDefinitionService, calling the new backend endpoint with error handling. |\n| **Frontend Interface** <br> `Web/Admin.UI/src/app/interfaces/measure-definition/related-artifact.interface.ts` | Exports IRelatedArtifact interface defining the structure for frontend artifact data. |\n| **Frontend Form Component** <br> `Web/Admin.UI/src/app/components/measure-def/measure-def-config-form/measure-def-config-form.component.ts`, `measure-def-config-form.component.html` | Integrates modal trigger: converts measure ID cells from static text to clickable buttons that open the related artifacts modal via MatDialog. Updates component constructor to inject MatDialog. |\n\n## Sequence Diagram(s)\n\n```mermaid\nsequenceDiagram\n    actor User\n    participant AdminUI as Admin UI\n    participant Modal as Related Artifacts Modal\n    participant Service as Measure Definition Service\n    participant Controller as MeasureDefinitionController\n    participant Validation as MeasureValidationService\n    participant Repo as Repository\n    participant DB as Database\n\n    User->>AdminUI: Click measure ID button\n    AdminUI->>Modal: Open modal with measure ID\n    activate Modal\n    Modal->>Service: getRelatedArtifacts(id)\n    activate Service\n    Service->>Controller: GET /{id}/relatedArtifact\n    activate Controller\n    Controller->>Validation: getRelatedArtifacts(id)\n    activate Validation\n    Validation->>Repo: findById(id)\n    Repo->>DB: Query measure definition\n    DB-->>Repo: Return measure with bundle\n    Repo-->>Validation: MeasureDefinition\n    Validation->>Validation: Parse bundle, extract<br/>related artifacts,<br/>determine found status\n    Validation-->>Controller: List<RelatedArtifactInfo>\n    deactivate Validation\n    Controller-->>Service: HTTP 200 + artifacts\n    deactivate Controller\n    Service-->>Modal: Observable<IRelatedArtifact[]>\n    deactivate Service\n    Modal->>Modal: Update artifacts list,<br/>set loading = false\n    deactivate Modal\n    Modal-->>User: Display artifacts table\n```\n\n## Estimated code review effort\n\n🎯 3 (Moderate) | ⏱️ ~25 minutes\n\n## Possibly related PRs\n\n- lantanagroup/link-cloud#699: Updates API base paths in measure-definition gateway service, directly supporting the new getRelatedArtifacts(id) endpoint call added in this PR.\n- lantanagroup/link-cloud#572: Adds additional endpoints and service wiring to MeasureDefinitionController; shares similar architectural patterns for endpoint integration.\n- lantanagroup/link-cloud#700: Modifies the same measure-def-config-form component; may have overlapping UI changes or related dialog/modal integration.\n\n## Suggested reviewers\n\n- sdmcgeown\n- smailliwcs\n\n## Poem\n\n> 🐰 *A rabbit's ode to artifact sight:*\n> \n> Bundle dependencies, now shown in light,\n> Which artifacts dance, which ones are missing,\n> Admin's concerns get quick dismissing.\n> *Hop-hop* validates the measure's might! 🎯\n\n</details>\n\n<!-- walkthrough_end -->\n\n\n<!-- pre_merge_checks_walkthrough_start -->\n\n<details>\n<summary>🚥 Pre-merge checks | ✅ 4 | ❌ 1</summary>\n\n<details>\n<summary>❌ Failed checks (1 warning)</summary>\n\n|     Check name     | Status     | Explanation                                                                           | Resolution                                                                         |\n| :----------------: | :--------- | :------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------- |\n| Docstring Coverage | ⚠️ Warning | Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |\n\n</details>\n<details>\n<summary>✅ Passed checks (4 passed)</summary>\n\n|         Check name         | Status   | Explanation                                                                                                                                                                                  |\n| :------------------------: | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|     Linked Issues check    | ✅ Passed | The implementation fully addresses LNK-4711 requirements: backend service returns related artifacts, UI displays artifact details, and found flag indicates artifact availability.           |\n| Out of Scope Changes check | ✅ Passed | All code changes are directly related to implementing the measure artifact validation feature with no unrelated modifications.                                                               |\n|         Title check        | ✅ Passed | The title clearly and specifically describes the main change: adding validation/information display for measure artifacts, matching the core feature of this PR.                             |\n|      Description check     | ✅ Passed | Pull request description follows the required template with all major sections completed: changes overview, testing performed, unit testing checkbox marked, and documentation status noted. |\n\n</details>\n\n<sub>✏️ Tip: You can configure your own custom pre-merge checks in the settings.</sub>\n\n</details>\n\n<!-- pre_merge_checks_walkthrough_end -->\n\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing touches</summary>\n\n- [ ] <!-- {\"checkboxId\": \"7962f53c-55bc-4827-bfbf-6a18da830691\"} --> 📝 Generate docstrings\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n\n<!-- tips_start -->\n\n---\n\n\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->\n\n<!-- internal state start -->\n\n\n<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEYDEZyAAUASpETZWaCrKPR1AGxJcAMgDkAaTAAFgB2AEZwrgBJDAAzfApmakkSSAk0D3haFPwsfDjIAFkSNAcKNIBBCnE4tDFkSAM/RwFKLnCAZlDgyCaAVRsfLlhcXG5EDgB6KaJ1WGwBDSZmKY9MXEw0Igp8bG41+AwAazAGDz3aKe5sDw8prp6+g37EdvtSjGYGeA8pDAwaGeAGU9hQGGkBFQMAxYL5AiEIuFIIAkwhgzlIuEgUMwsK4SgkIM2uGwk343DIzxsJAk8BIAHdKGTEMlfll6QxGgYAMIVah0dCcSAAJgADMKAGxgUXhMDhACs0HCoQ4wWCHHCAE4AFpGAAi0gYFHg3HEeQ4BiglVotGQQPI9Ox9WOZHo+ApVDNWAIkAqJIoWCOCSSuSwKj2WKBbDK2AqAHJkBV1jR6M5avVcIgNJbiop4HE6chcLA0v1opAfZkLo6gaTKBX8Iwsgxjvww5Bo+U0ph6LSGSh4olkl70AIIxXYNQO6UuwnfSRkwK0/mM1m3NJxBgiDxKMG2LQLVAAELYX6RjD0aEDyC0fAtyhnFjcfBvADckBIAA9KD83vRi2ksKYKQ9CIEaJCUj2A40FQYjwHkRaNkw8TwEkkBxNgMJepk6jyFBaDcBSzi4iQ2YvBg6gVhuRxEIekD9BRWI0IgmaQJOUjYhBWD0saYyUokkD7DkKYNgoUh8ABjCTlu0iQAAFLCogurQACUZF6nejjsKGdEaQwWkYMS8FYEJ/IHpAfhTJU5iWAA8sIojiFIyBxLszCQFkJwCkgDjSEYABibmQP4QRhJEMSDiGTlpBkWTCcZ/CFCUMYVJA1Tpg0OZWLstJKPYsgsSQ7loLQzBHEguCeokRYlqOvy4aJfaOvSCCwugNQrg06DTilaRKBSF7IHk2ZQLEtDwAw/KQC1JAAXwpRtf1rrsO1GVYqgFwld5hmNpJiAFTQzAjZAACigICF46CleVLFVRQiEoEohn5vIZWIIgNGrZ1rFtMGaT7Jt41bt1Do9V26RMgllYSPg2S+ph4hsB+376SOvCCF4zBrgYFiQNyLBlVibDvdsskOE4LhGFA+OsJRUSQLElWKNgEI1ZCzquuSygjj6fqxlgnaxiQYBJmZX11GIA57qG6AXgoFAVIgz4Xp9ZZScBsk+k1E5TkGQ4y3ITYTccn1RjOQsaM81ME5RwpcNatpXeN2EeAoeW3vpbCGTLUGYZRzGZmR+jGOAUCcwUOAEMQZDcwKKxe0KvD8A5cHOdi8hMEoVCqOoWg6MHJhQHAqCoJgkeEKQ5CenHBPsFwVCOuTyQuOnbvKDnmjaLoYCGCHpgGAAUmgGRTILFQ0pkUyIOCo/aBgUxCMPaBTCsawbFsOx7AcnnHKP5vj7FK95EzdxMlMyVdgaBaMcZ+OGbsp8UBoi8ZBaABEH845YlTRNHVdi03Zw8gI5ARkogKmaUbRLkgKDJaF4yAMDwnLUWIk3gUFpBCaCJAdg6QMH0UazBnw1AFNSRctB0rfViAkWW9AL5CwAGo4XinkYElAMGkTwboSABpzjOGgaDXgkgprX0yOhOkHhexMNDKw9BE0OH4NOp+Gg8D6DIVuizAgElGz1AhKaYo+8SCMLitIthciaEDnUPAHCAAvAUkkCwLloMdRmuxaAswFKDSoVhyyumfEcTgnCrRQPoAAcROtASAUwADe2QAC+UwUF0AoRLJijY+YBm6lkFiiVICkLMskjMVD8DZgUWdWgfjDI3gXNg/kD1YrZBMbIiEGhMR5JTAUhoclshqRzEUI4Al6SoU+qA0gkxAn0W4MJOO6x3ooEIYkViUE1GVQ0QJSsDB46KCmpJUG9TmFYDQewsiPgjiyRGXQLgABqLoUw5RGBOixeAw4a55QqNrEgcRgxChKONRwBgP5vypv3IeI8x4QUPtPBgs8jgLyXkfVY6xvaAk3vsQ4Jw969QnvcZgigFyICmG0pJHUUlFOfkvd+n9cY/z/rHUCjhm7AMKOc8BOYHZ2hgf2G4F0Jo3moFGXFrteGzMJeQ4lhTBzXm4M6UmCgjqIs2Mi3Y+wNA7w0GCrFaqBVrigD4FgY5WyV1pegDZ0hEDVS4AAARCbNGC5iLWsL4nwAi3Ash2N2rVIV2rrCLGbGIxxyBaRAkxDBfFbxHVkkBEjOSwJKo0RUgAGkEhQV20bY1bgTehPYcs5JjnwF4TAGasg4mNLJOSRQCLABjcaLciaq00T0Bm8SH08jyTrem46RaqAluQCXG+NilzstBgACTKLAct3BgB6FbkoOotxNBGBOeQZA5zzLXNCLc0U9zHnPNUbi+c7zPkLK4EO+ARBYD/M/paYFcL1UQpnqyeeL9l6r3lRvJV28ji71vZPQ5cj8V0IqEYhpXoZFHKfRSwFVLf6GurnSimjL1ZgKMC45mrMQb9mBII4Gv7MEAcMVIkDpjMHFinOjVmbx2VgrnCeC8l0fRKBgmVcg84yHi1XPJOBT0fjSBUlU3hFR6BHGCvAYt8hFZglZpbAIJB5BtHYvBCgFocy6pKuyvDV9yojkNtEPU6QrH6N6hpm+eRqTPg+po2Q75KC7HutNeYkBgiil6PmGB+AsQJEwm6PgjnRQoEKAITzl1UBvQ+luZxMFan8HEhONINHaCXXYN20STBT6S3E7GTBgwfCIETaSU2bEFwekgK06QEmSD9GTXJakZqMskF4yRrE6SMDsqyzwF8H0LryAcJ8+A356CDOLN1JtCU5LSz4qmZAsYPAAB9hstuDPozYwk0DVbKz0nV+AiCJlK7VhQCNzHqFjsgTtzhCyiSOErRyuSFz5LFZLRLhZjr+QEgtWA12yEdKxBHXAsgKTcJOlYE6fg9TAlsn4RNp6MCJFkll5AA23u8DoB8059BEcFm/Dl+w+wiGsXdC7CG90EpfkqhmBKrkWBsclrD+SU3ZuQzyBmpZJYWw9sKJJZcKT6JDBQMgRHbxKlCckmC7EgWOFQHLf4ue7KslfcKCKz7RTk4iC6nJFFFJ6CGw5xmLnPgnRvETSxRIn0puJrmxgRN40lbrHkJGkgiaPNyziOsIgib8IdmdZ9COJ2ksVDiJQBBn11DrYmVM5A8u7u4EVxdhVaH4ceRE12+QWWwC2/d4RGido5YzTmjFynWJ6RlEzZ568kkAu0bF9YVx7jkBKAC9uC4W3M18CYAjIahR0vgmkImxJqYI+Y6glD3AYAHe97Wl66k/pmu57KG8ZgF0BQy5yeHtaiuKh8/YJ9TjAeu8xdQjwRWCC0iC9qmX+LduCfNsDJFYcxlXdyxn3eKxIlvePfuQrAS0l4s0Too53oM0BYGJVLXyWItqoCD5F4XjHQ+bTQlgAG9RAGaYJTrAs7dSn5eDHTAgmwTAwK3Cuwd5oZQRHB7L8B8CQ7Q6j7fQ65rjPBWA+o8peLRB0R3zqJiACR4ZAb7KgZyJloGJGYgEYCmYvjqCJBiYkBmbCEuAqRZR0EMDCYsTADL6UKDhTolYfZ96prVrbjdJGDZRCI0AFYeAehjJQBtrbglY1ad4VYeBVY7ad7zgWEQhSHNBubeBpR3AeSbY8olyEKYzsBLhEBS5Yj+RDrRB2A2C9A/YUjIByRxZeCJonKiaJqKEpJJG2GOHmJ1jsoehgBZZTC25Kz1DdhEA7A1Iji3T8hEDyALZb4wiv5fxND1GVAeARZegPSSRKD8ahht7Iw44CgCRcq+ob7iB+Q5jcgzJ2jBJcADE8qeoGZdgcGNLsKSrSqkCyoqrryKpbwqqfpqoGIao4Z+TWzNYrKsFOqTE8AyFzEMIEbGRcEQg8GGbI7GYCFiFCEWbzjiEWa8ZCazHsE3EsJEYkC9KzSwCKBOwXIXHcqyEnLyHJHioJAqGzRwmdKmGPTfFYC/EGILGEZNJAn1HloUR+7ZL+S/BVCAgeCyC2IUALqnLLrSQgRXLhDBCdAbpbqIxiyZxpBvJ0iOgfJfLHqnrnoApApgBGAgrLzfr3CQpTABywojwvobHbDvpopfp7EQqAn/pYn/EYB3EkDQAbhkqvwXqQbfzQYxywZY7wY5LMrIb3yoayT2j9gBxNgz5XGAbam6n6nZILaSR/HGI4lHL0QUa5gtjCGiQ4oti57qZPH8GCHmYiEHYYDK6sT+LuppAHGWxsodhzomh0YbiMBlCyQLaqG3Zj5KZQB+BubPaeb1yvHxktxNbIBFSmiWY9GORh7SDKxvAxrUCkgnSfi6Ijhx5+C2TQAAD6/ktk/QwO5ixMiAMqb8eGCBzxrm7mWatAb8x0lZsRrhwuM6iBLak4yAGAuBIu5eVmn4FIXUR4lQeoY5NgJ0AAiv0CdMCBEnHnOQuUufuSubeLJOAchJsEJkCGgSQJuTmMCCzORlwMshQBouyjuXZoNi/g6XLDUdxnUgRt4OMgaANFxrIMiCPnplGNQIpD2lgKBeYg/j8GLHHrgPSI2ChdQVwrhctDCLIMKKuRAbQFZs1kLMuokBUJLIPsPuuWxD2J5EQCUlwv2ecNgEoMeXkGAHqADkDiDmDhWL9qhfQGwEtnymAFkC6PYWVsxUcQWEkNtg4M0QJd7EJpxVrpLHrHDvZkwArFdrDqbvTs1vbmJU7tsP3nLExWntwDRNJVANibJJ/pJTklDhgGALpSVHysZbVtEVYCkOwLxobGQOUJ9OAURYbJNLFRNKIllmFadHxYrCgEQFDpoTktyI+f5GAGjr1gKNTkJuha/govQpQPmGdnkBSSxhPJUh1Q6alEcHJUoIJlgIrHOtjF6axEwNFswDmS6mkHQKsZNBRlwCFp9KBYmrFfFbNIlZsMlZ3gFfQPVf5DrvvsjhjpbHAGkAHNtgNS2gPAxJRPKImkUHeCbAQHfvQJhpoYAJgEHZSsCEJAPZJIiAslYhI4C21mAkYEZAp2L4ZERgjRzR3MxkbRtUHR6wno2NOSX4vRXmkJgxz0wxLKFZjYxNCyfRfA0xsheNxErR00/u4JpNOK40Di9ACk4xs5IJigdoqUUqLYpMTVxoGQ+hPpG4iAPSBgi6Zy9JEJlyYomorJBgDy7JIknJ+6PJH4h6NQXAPy8AfywpV6opBgAA6iQAIFZNdBgBoGWFPDPM6vCsrOwPimCmADOhil2D7R8o+ChEQKJUkH7ULAHXEEHQWCHXuMsE+HkOwBoKMMwB4BBo0Waf/KgvSkAtacrVTQzN6LVN7TOtHaeqHUdCna7IdC6vyImpJDpgoB4I4FgFDo6BUPArZpJNUgnBoHDIXkCOcMbCoJdIIgyo+BcAJiLmMC2g1hWMaMUUyFzC8WoWPt9TkNYT3RlW2EbC2N3mIcgZ9JJIjrSHsLzusILsTjeEgLXQhlvYZH3U4jAAgHSRrGzIwAuIKsfCtOTu5CxCkLITQEoqJGXP4soKnGtb4YZK7pjbVZJEPZGXJsPApuYjSD/dWEhaCXgIhnMMDO0UlQ4WkAJCli3fYCcf6BwujVSrA10aJO0aIPjbQxHLTcQqTYzR+BTYWBApWTg5rDTZeXTVcOw8zQTQhFUjQGIHQGRLjASfmPmSSZdJUOSZSZQDSUurw6uiyXcprduhyXutyf2HyUevor8swMaSKUYDbXbdaExk7dEC7VCm7SsB7YZF7QYpHeHRUJHWXbHUOJ48LKXchDHRXfHfMuQA/ZmOnVBjShaYAi3CAvnRAg7AKFzaIg4IRMY/4lXrhtQHqFYg3uYsiZmOvZkDTC47gPvXMIVHwOWrgHk5kJtuvbcOfoQUmVdrU/UwU6mbns44nQ/TmP2VKiorKuU6JO6JBCxmLA5axKk2nRyo6OMyvaWd9IgCU9YWClfLxrpaCf+JOF9gNB2avSs2s2U30/nvZkLrwR8o/egDXklVBIjj+QKONF7Jfl6v0JMno8cXBacVwG3QOMmcgB0/k5tugBcFuB9HlF+BVJ9AcV6tAMaKwN5PMjUGSBUDilIPQJhHWLuqlEo0QLcM4HMjjpnqmMEsULkyCyHT3sSwsl6rQVCWlN4rw2SCVJNcvUU6s1sq7Ns2Cb7J8zrQhOQ4jZDr2alD6ONc3e7FS1UnhQgrIGjRjS0YTT6PQ50azcwwI6wyQWTTykMVw8CcWHy+cQAAaLOctrNyQbMfIxDRnAFeh3wx3r0LgqRcAwzZAmvXizEmt2sHkYDPZJCnPhO4CetCYmtWP222PO3SlOMJ3BtuO9QeMl2B1BPl17j+PeOpu+NJChPlMaCZgmujFCs/OaL2CisUOCQCsQk+tXP2vGQBvMBBvsCeuwWrJ8D/OSvyWyQmuCJS19RUvG2UsNNEChtYDhu22RtHB2MONTCxthOe0Zu+3JtR1ZsV2Lspt5DBNx29PBv5uICFtUOWCyNElBGklpTKNUlqNK0ayroKi3LyhslPJ6OvI0j61GNG0mOm1mPm0QCW0Rs2NTvRuu2ETu1nMJv+2+095gDTOIDxXcsJI3YpjQd95wcb25tnPJ24Cp1ROmkxMAI53xNMqJMGAoZuIEHzPnsEv40jNnOQBDrQBFC6412LhN7dSzMVieAChvwippR96sdRJRLLaP2xKxKbnP2ljliICgn0jGFpQeElSwvEhpBx5AhKxHBVzHSVC8onWbDz7yRSf4D0jcSwFcWAxxrx6PLAwweYNN0t1kh+BoBsCJrdWE55CJpZaJrVmQE5gOdIwQh3A1433W7dQEB5riDcA5JBWBrFazQJGJ4wm4ByTTPbHFqFi8b4SEQDUiVEUsSyDRUubJdEWoB1AeBvDHQueX7mKtb+elfoCZc25uaiXF65fRX/554aBFcuSZBlc5hee7rN3MAHLSfsqKQthjk/DghBbIQwGQQR4ddiWoArLn5uYlgUCDJvCywfjv6kHTcpbkHTTOCO05jQAj1cnLS1WoCAUPxeAa7yCW6310D4wDfNbHSdOguk5iOdt5RAhjEviQh4AEBHc8jHwPzoTVh0TRCFBmfAyLdwXn4GeNwhUAiUBWaldned0VinfHTQD4BhcmjmLITOzGSiITRiOcY72FdiX4TvSP5izLZ+oSLRG26eWufm5JoeCJpMXB6/cbdIOn2kG845TZACiGzDg+1UtnAXAbez21Q8//cz1A82RuHKtiOqu40MMs2E2ask06vsP6sjHU09GCPXCXEiO0Nc29V0BXuv0ySaPq3SiPs7ptx62GOG3fJ0BfvmMW2WMTsAeO1AeOMgc7sLvLsIdkLIdj6oeTxQcwdR8eDoe7tgTvQ4dpSZ1GpxMIY2kGBZmOmOjAjcjAjAhkN5fSAlizSseSQx8ofsfB/QPQTZOKd5efRwVeAPRXd5oeRoCyDjhQS0gODdd0RqfI8UBB1AVVwwV+G2aAUrRx5So2ihU5hi/jTDuj91zX3znz7IDJCfhgAliClYiwVzyBw5i6deBcBhouSnmDK0DFjHTZfrm1m0CJpjgSJURKLHS4C0AADaYvNXAAulwAAAc3AT8DwDZYL8oAHADgFuADpiFIAaqagGAFC7NETQXAMgMGDQyI4DKpyGAodjAAFFmkzhTiPJkSCiIG8PKASPTyirDJ8674G4EmHkDr5vY+OFrgv0PbK8saqvNMnxkYYatCgLDESP0UuL68C6lZcgNbw0ZXJJQGtLWk+0FYvsD0/JOjoKS96/sfe1jB2tOxjZB842IfdxpB0Q50AI+KzOPmHzMjGCUksHWZgnyTqRNzG0TGDPhytIJM36tpJmGRwdIUd/6F4BpsxnxaEtm8ugypBa25ZNtKkckf9poID6zsdB87VxuuziBmCkOsfWZkkKMEpDuWNgiJnLXuoeoghASHMLEEBbX1h22nIENFyKCVBxyeoaIJUB8C2QQkY5PUFUK06+xgyvrZ4rqVEh+5cAbUGltZ0NjH0he7LOGKAT7RZBrEoYY6BLlspT5/6NAWskc0sHyRQihg0VGtC/5/9C0+ABTsDBzS4980GARnGhSC5d9HueaOzvJGZ4X5b87PHyp5mDzZR8AuUWSAjT4DUDgYgwzbEQGirQ9twPoErtLwOSAktuNmY6IMz+7soSwhhesJiDi5AIEuckJigAH4uAUSSAF/xdCyBz+aaIgAALIa1VYkrrAkUfUbBjZ48omDhrGgdLIA34qeOSLGHgAqQ34HwKVBaUNgOhPI0gV7hr0qreCcgFAegP4Oo5c1mmtLVFqx2eTGhREtfRZHLE2QmRxAWQSmuCIEbBl4GeaLwJIwoLLCJWrEZjsIgEgd0s4gedsNYKV5K8miKvKfGrz6i8imG/ArVoIIZrCDOGBvPGPzTZbVsQhG9MISG2vDjsNBUbextoIOCyjwOEdAweHwyEb00htACwauDj5ZDNABbaQlCRN5QkKSYAPviJkuittTiZbaqmK3+hVteaXoqasmWxqutxkJrfMZojkgWoihjkMtFUKaG1D6hjQ5odAEqC8ZhGfKNEY9BxGEjE0vbKaNazrYAlcSxtWtn611IqRC2UABlr6jYBz56w5Yi0AohNY95PsZIVYUsIzCbDIAAAXgxF/9C2m4+7tbnOHPdmQuIw8SeK/5xhbccYRNHGDNwvjIAcYKbB+LjAj44wZ4msX8OPHz1sAJAT1l0nGHwBbEqkNMcuMFpktJqG4rhCazhEJ4ERFUJEWhO7SojIA6IzETJiHE0R8Rt0T6ESMIlbgFxwmP3IgnOBpBQS+AVsOuJrFbhbIGAWIOoDkjEj3WtAT1nHnIGAMkIVYSACa3HGzjASLSJEmsJ3FyRiwSADQEJ26Set+WUyYSduL7xKS5YJrP4Z6wECFk3QY7cgEohNZTATWbwz1lKmLAsoZGmAORsSTPZKNMgKjakgrVpKSDIAlyeUFo03Q6NtaLyM7ooOMYm0zal6NQdbV95RCQxwHA4GAwoASxpACQv1nGITFiA+6hkXcIUT3Yp9qUjg7Os4KI6uDChdpDwYOn7DQAtKwII0CaHWhpTYphRBmEUyN7atf6kASIcGJnZu0YpcUiMV4x/L8EkpyXTqRlOP5Fxaog0zBF9yLLiJbQfzRzmkDkgkT00LPSrnJDxzE9XYC0ogBmimz6dcRhaLCWdhWmmg1paeHJBtNEgbTjh9AIivsLzSfB5aSTclgIO2gwQ4pMQIphEPCltTQxUwMafFOXaJSq+a0VKS9KGly0bO9DMCMaDaBXSpp2MRWjbwZLuT10DvHyXIL8ku9eSbvacaY1UH9xWpgHSKYHwOBwtZg/IAvLIASnPF/GGgDMnYOFIODzSTghlHnQKlBJ2WufXVrIV5b0ASy7SdQtkHImbSuA9kQ5Kd2AB7jlmKSTYVOiEwdD+CXQlqBNDew+RQJ7KMJBEgqAABHVWaknQizQ+hawvPC5AEhBpUgcBcGL1K9CJo+J3wz6NF02ARcoIbw8SrRjtn6Y3hI6cvE/EKnuD3EqYCjpESPwossQEsvmWtCorksNRblMGirBh7Bz485AaYf0j4BjZNw24EqEIFJBYdPa52eOfMKKie1jkrkldIyUAG3JABjvZ9v5LfZYzP2wUwFFel7iFwOGboQoGgDwAVxGZgrJFoZHrhoBG4BHWTBnFxTZw1AncfOD3AMDNz446gMctkEQBjkDGjIWgGOX/o1Bu4Tc0OB+AlAShABpQYIBKGFChBhQR8zULQDiBKBPJwQD5MKAYACB5QZ80UGgAlCah5Q4QQAQwHlChAJQG8vuFABnm4A55toRea+wZB0AxynMAuFvMRxjk2AFAUgON2ZzHAF5a8rEMHAMBRJOEb8JALZHEjGgoEGAN+FwEBF24sFSAWwEeAuD3haANMBOFYBfApgiF6EbrqQr6BvwDOtwWgJQp+q2AmFJC+NFgvGi0AbAmEPSKYUQDcgkFTCpbgIrYVCKRFGAdwLgC8CSKlI0iuHrIsgBvxOSNgFQGPKtq7AaA2UJRV4D4UsLNFb8eRaIsNDGgjpeQVRS2HUWgSLFO8OgNEHeiqyq0TCt+AAB0MAfinxbgECXBKgloS4AK4pXkqySAegAJaEpCUhKLAlgEKIiHCiF0xsqQdINqRyRLkdxAS/xXEoKWBLcYJikgHkqKRRQMleyGWBHByV948luMA0JDKqnGQ8llQdlPtEKjFQHaFUO6PGnLAF5KkPoNoKODoyNhtY7OPjnPTNjwFOMQ0MMHLDeDKcSwOeACHhFSiAxnp3AjpYdHjRmodY60QoOWABg7D/ZoMYXGbgZgFlgRSy3WFvx8imx783E+GM9CRhfhRAeABKOjHnxYxwZxdAxBoFiXxKClwAFUuAqiV6A34LisoLgAcXHBqss1JhV/04R9BMFfQNFVotG7HBfOYFLgG/EXTKQGYHipWmos0Xor2FxIUkE4tYXoqtFxNRFKGG8UPViWUDIyPNlwJ4QbQisYMskrCjIgtZp4dFp7S4C6T7wCykEY2UmYiQYO7ncsJeK77C1w5DGbQKV3+rcUwe2wAcONEmjMQ886ADIL8BUD1QfsGgSFcirRVvwuaOKrRQXgDA0RTVNKrRUJU3anohYZitHqSvNVG5cGpTJBdiu8URL3FvkRAG0oowsh2AgKdFbEg9WoqaV2i31bNO8W2RsGEcCqeMzxj50pIJKs1WwvmGUquAMi7NbSsvL0qvQ3ipol/TyjMp2o/bISsotEKsYJWPhAuc9DwZ/L4C0zTJf6TJylAK2ceKHIJAwA0sLeBYbVdjRNUeq2Flq7xTaoohbh7Vsap1cHVdXELzFhat+F6qOA+qlIfq3FRGFshxBU1FISRW/RDWmoE4EatFVGrNUxqyVmKndVor0hnT8Y4kUmPOrJW5rEAbq/XGurpVbBS1uKx9biLEjKBViqABUBoE6CACAApLgLai9pusI6ukA/XE7zhtZqEOxLAEViglX+qAQAaKA0CihRQUG8dWuvEzN1/1WigxYdhvB3gNpxsiSLVAwhYRCaO1VtUVHOkpBEAcQeQBqJfWrFiwWGvNE4jfXmqp1uKmdXaonVaKN15JWFfessW0bcRn6s1VevRU3rzVd6hNbipKWZrHFUm8lb2U/X5qNFP64tX+uMiMrao4gZRYBHzTJokEoEK8r1Umh3A7uNikTJrGLpzxeGXAcAcDCqVegfp1+GWHKqqICRhc0q93L0IQBsb5YaQP3MWJySyTkAtgEjQ6otW4pp1h3STaRtEDOqCWFQL9dSrJUyat1LYeTdZtMUqbo1a6zTWwG8WNLKpdijElIv00fqqV+m39YCAo1vxaC7hflfmQUpNa4amowzu/X5Xob/wzZFjip3cLJAhAiNRyITWcZeAUwMFDNc8NMQMh661EYGB6D3B0BcsjEKiJZ23CYqxwoA5uMpFVUewDIrKg5BSsUopg0tsasTdauy1zr9Ni6mOsuuYXuq11pWjwHJq01aKhtti0tSps4R/8oVLEWwCUu8UShRQcQI+cKHCACAkdcQToPKHlC0BQg8oO+XEHCAShv5hO0IOjsiC0BVAmoJHQwFCAfyBAzJToOEHqACAJQaAOoGjoiChBNQcQeUAfLAow7cAtgRreDos24rP5cQCUPKAlB3y2dDAQAQIHCBHzaA8odnX7hICihad7O4UNfPZ0q7OgwoWgJ/LoCADNQwoOIK/LFDBAGAEoToIRpIB07NQnQOIGEHnUKbOQuI59SBpICMxKA5JSGlavU1vxxS/jLFDOwfRyln0LANeEiiVJbwVSoe9UriU1K9RsStxcSU+iYXqa2FBATYB4H8iYQ4ICEJhZ0H01Mai9zWK2vMEA2aEjNIoarWauD03o1SP6e9HPEj3woY9CqOPaih3iJ7J47fR+CnsvgxkHWIPTUZQENJoAs9a63PZkAL3Mbi9XAT6muvL2tEq9xYGvRniYWbpI1HqpvaChb1SkZ4spJ9J3tfSbFe9n6fvVKQ1LnwtSXaycewnmpT6Z96WuffnsL2tEmFK+9LWvuxob7YAW+iFjvsh19BYkBgCA1POgUVBYFlABBZioXmQKe4QAA=== -->\n\n<!-- internal state end -->"},"request":{}},"response":{"url":"https://api.github.com/repos/lantanagroup/link-cloud/issues/comments/3756106573","status":401,"headers":{"access-control-allow-origin":"*","access-control-expose-headers":"ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset","connection":"close","content-security-policy":"default-src 'none'","content-type":"application/json; charset=utf-8","date":"Wed, 28 Jan 2026 23:31:40 GMT","referrer-policy":"origin-when-cross-origin, strict-origin-when-cross-origin","server":"github.com","strict-transport-security":"max-age=31536000; includeSubdomains; preload","vary":"Accept-Encoding, Accept, X-Requested-With","x-content-type-options":"nosniff","x-frame-options":"deny","x-github-media-type":"github.v3; format=json","x-github-request-id":"403E:82DB0:191A661:69175A8:697A9C5C","x-xss-protection":"0"},"data":{"message":"Bad credentials","documentation_url":"https://docs.github.com/rest","status":"401"}}}

@seanmcilvenna
seanmcilvenna merged commit 0eca23b into dev Jan 29, 2026
16 checks passed
@seanmcilvenna
seanmcilvenna deleted the LNK-4711 branch January 29, 2026 18:44
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.

1 participant