Skip to content

LEGLINK-620: secret-key-on-Vendors screen - #1789

Merged
arianamihailescu merged 16 commits into
devfrom
LEGLINK-620
Aug 5, 2026
Merged

LEGLINK-620: secret-key-on-Vendors screen#1789
arianamihailescu merged 16 commits into
devfrom
LEGLINK-620

Conversation

@arianamihailescu

@arianamihailescu arianamihailescu commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

🛠️ Description of Changes

Added secret key top Vendors screen

🧪 Testing Performed

Tested locally

🧑‍🔬 Unit Testing

  • I have written or updated unit tests to cover my changes
  • Coverage: 100.0%

📓 Documentation Updated

Please update any relevant sections in the project documentation that were impacted by the changes in the PR.

Summary by CodeRabbit

  • New Features
    • Added vendor authentication settings with optional Key Vault signing-key secret IDs.
    • Vendor creation, editing, retrieval, and version views now preserve authentication details.
    • Vendor editing is now always available.
  • Improvements
    • Added validation and clear inline error messages for secret IDs.
    • Updated vendor API requests and responses to support authentication data.
  • Tests
    • Expanded coverage for validation, persistence, model binding, API behavior, and form interactions.

Captures the decisions behind associating a Key Vault secret with a vendor,
so the reasoning survives outside a chat log: why the association is
vendor-scoped rather than facility-scoped (Veradigm needs a different key
generation algorithm than Epic and Cerner), and why the stored value is the
Key Vault secret id rather than a JWKS kid, which LEGLINK-63's title
conflates.

Also records what this ticket deliberately cannot do. The update endpoint
that persists a secret id is owned by neither LEGLINK-620 nor LEGLINK-743,
so the UI is built against a single isolated service method. LEGLINK-63's
audit-trail acceptance criterion is produced from backend managers onto
Kafka and no UI change can satisfy it.

Claude-Session: https://claude.ai/code/session_01STFKxmDaJenKVny6WUoWKo
Link signs the JWT that Data Acquisition presents to Epic and Cerner during
client-credentials auth. LEGLINK-14 moved the PEM into Key Vault; this makes
the association explicit and vendor-scoped, because Veradigm needs a
different key generation algorithm and so cannot share a key.

Add an edit path to Vendor Management. The dashboard grows a Secret ID
column that reads "Not set" when empty and a per-row edit action; the form
grows a JWT / Authentication panel holding the Key Vault Secret ID, expanded
when a vendor already has one so existing configuration is visible without
hunting. An emptied box travels as undefined rather than "", so clearing the
association reads as absent rather than set-to-empty.

No update endpoint exists yet. The Vendor model is moving out of
Normalization into Tenant under LEGLINK-743, whose acceptance criteria cover
list, add and delete but not update, so this operation is owned by neither
ticket. VendorService.updateVendor is the single place that knows the route:
when the contract lands, that method is the only edit required. A
config-flagged dual path was considered and rejected as permanent complexity
bought against a decision expected within days.

Two defects in files this already touches: createVendor was typed as
IVendorConfigModel while callers pass a name string, which interpolated
"[object Object]" into the URL for anything else; and getVendors never
cleared its loading flag on success.

Deferred: the mocked Playwright spec the design calls for. That harness
arrives with PR #1773, which is not yet merged into dev, so there is nowhere
on this branch for the spec to live. LEGLINK-63's audit-trail criterion is
also outstanding -- audit events are produced from backend managers onto
Kafka, so it belongs with the update endpoint rather than here.

16 unit specs pass; the app builds clean.

Claude-Session: https://claude.ai/code/session_01STFKxmDaJenKVny6WUoWKo
…itly

Two defects found reviewing 4b894e1 against the design.

ErrorHandlingService raises its own toastr before rethrowing, so once the
save paths began emitting failure to the dialog -- which shows a snackbar and
stays open so the admin's input survives -- one failed save reported itself
twice, toastr bottom-full-width and snackbar top-right. Saves now route
through handleSaveError, which suppresses the toastr and leaves the dialog as
the single surface. List and delete keep theirs, having no dialog to carry
the news. The rethrown error still carries the sanitized message either way.

Clearing a key sent secretId as undefined, which JSON.stringify drops, so the
field never reached the wire. An absent field reads as "leave unchanged" to
any endpoint with partial-update semantics, which would have made clearing an
association succeed visibly and do nothing. It now travels as an explicit
null, and the design's open items record that the backend must honour null as
"remove the association" when the contract is settled.

Adds vendor.service.spec.ts, the service having had no direct coverage: the
update route and body, a cleared key surviving serialization, name escaping
in the create route, and the toastr suppressed for saves but kept for list
and delete. Both new behaviours fail against the previous code -- args[1] was
absent rather than false, and secretId was undefined rather than null.

21 unit specs pass; the app builds clean.

Claude-Session: https://claude.ai/code/session_01CX9BzMrPhTzGSakXYDaAVa
A failed createVendor had no test. Assert it emits a single failure with
the error message and does not fall through into the update path.

Claude-Session: https://claude.ai/code/session_01TDPYGwkQDCXConLTuyU4is
VendorController exposes list, add and delete only -- no PUT -- so the edit
dialog added on this branch would save into a 404. Put the edit button and
onEdit behind a vendorEditEnabled config flag, shipped off, following the
existing AppConfig boolean pattern. Flip it once the update contract,
including clearing secretId with null, is confirmed.

Claude-Session: https://claude.ai/code/session_01TDPYGwkQDCXConLTuyU4is
Validation lives on Admin.BFF, which already holds an ISecretManager and is
independent of the Vendor model's move to Tenant. Adds ISecretInspector and
PemSigningKeyValidator to Shared; the UI warns inline on blur and on save
without ever blocking the save.

Claude-Session: https://claude.ai/code/session_01TDPYGwkQDCXConLTuyU4is
Eight tasks, TDD throughout: characterize EpicAuth's PKCS#8 behavior, then
PemSigningKeyValidator and ISecretInspector in Shared, the Admin.BFF endpoint,
the Angular service call, and the form's blur/save warnings.

Claude-Session: https://claude.ai/code/session_01TDPYGwkQDCXConLTuyU4is
Vendor moved into Tenant under LEGLINK-743 carrying only Id and Name, so there
was nowhere to record the Key Vault secret holding a vendor's PEM signing key.
LEGLINK-63 scopes that key to the vendor rather than the facility, because the
key generation algorithm differs by EHR.

Stored as a JSON column rather than a plain one so later vendor-level auth
settings need no migration, following the AuthenticationConfiguration precedent
in DataAcquisitionDbContext. Only the signing key lives here: TokenUrl, Audience
and ClientId are per-EHR-instance and stay on the facility's authentication
configuration, where EpicAuth already reads them.

The value converter carries an explicit ValueComparer. Without one EF snapshots
the property by reference, so mutating a field on the existing instance is never
detected and SaveChanges writes nothing -- a test covers that specifically.

Update treats a missing authentication object as "leave unchanged", matching how
Name already behaves, so a caller that omits it cannot wipe a configured key.
Clearing a key means sending the object with a null inside it.

Vendor versions expose the parent vendor's settings as a read-only projection,
so consumers holding only a vendor version id -- as Data Acquisition will -- can
resolve the key in one call while writes stay on the vendor.

EpicAuth is untouched: it still derives {facilityId}-pem, so nothing changes at
runtime until the fallback rule between vendor and facility keys is settled.

Claude-Session: https://claude.ai/code/session_01QoUHyt1ALkruCbuYxHSXiB
LEGLINK-743 deleted Normalization's VendorController when it moved the model to
Tenant, but left this service calling the old routes. Every vendor operation in
Admin.UI has been hitting a controller that no longer exists.

The API nests the signing key under authentication; the vendor screens work with
a flat secretId. Translating at the gateway keeps that difference out of the
components, so a second vendor-level setting only touches this file.

Create now carries the secret id. The add form has always shown the field, but
the create branch sent the name alone, so anything typed there was silently
discarded behind a success message. Both write paths build the same payload
before branching, which is what stops them drifting apart again.

authentication is always sent, including when the key is being cleared: the
Tenant manager reads an absent object as "leave unchanged", so omitting it would
make a clear no-op. Null inside the object is what removes the association.

The vendorEditEnabled flag is gone with it. It existed only to keep the edit
button hidden while no update endpoint existed, and PUT /api/vendor/{id} now
does, so the gate has nothing left to protect.

Claude-Session: https://claude.ai/code/session_01QoUHyt1ALkruCbuYxHSXiB
The vendor signing-key design and the secret-id validation design and plan were
working notes for this change, not reference material the repository needs to
carry. They stay recoverable through history.

Claude-Session: https://claude.ai/code/session_01QoUHyt1ALkruCbuYxHSXiB
The previous commit swept in five files that belong to a local development
setup rather than to this change. Both appsettings.Development.json files in
particular replaced the committed SQLEXPRESS defaults with a machine-specific
SQL Server instance and a plaintext sa password, which would have become the
checked-in default for everyone.

Restores all five to their dev contents so the branch carries only the vendor
signing key work. The AGENTS.md documentation, the check_health.sh compose fix
and the Admin.UI Dockerfile npm layer-caching fix are worth landing, but each
on its own terms rather than inside this ticket.

Claude-Session: https://claude.ai/code/session_01QoUHyt1ALkruCbuYxHSXiB
POST and PUT passed the administrator-supplied identifier straight to
VendorManager, so an empty, whitespace-only, oversized or otherwise unusable
value was stored and only surfaced later as a signing-key resolution failure,
far from the admin who typed it.

The rule is Azure's documented constraint for a Key Vault object name: 1 to 127
characters of letters, digits and dashes. A value outside it can never resolve,
since AzureKeyVaultSecretManager calls the SDK's name-based overload. Note this
is the object name, not the object identifier URI an admin may copy from the
portal -- that carries a vault host and a pinned version, and pinning a version
would quietly stop key rotation from taking effect.

Implemented as IValidatableObject on VendorAuthenticationSettings rather than as
checks at the two controller call sites: it covers both verbs from one place and
matches AuthenticationConfigurationModel. With [ApiController] and no
SuppressModelStateInvalidFilter, an invalid value returns 400 with the failure
keyed to Authentication.SigningKeySecretId.

Null stays valid -- it is how a caller clears the association.

Claude-Session: https://claude.ai/code/session_01QoUHyt1ALkruCbuYxHSXiB
…cted

The API now rejects a secret id Key Vault cannot resolve, but the admin only saw
"An error occured in our API" plus a trace id: ErrorHandlingService prefers the
ProblemDetails `detail`, which is generic, over `errors`, which carries the
reason. The vendor form now reads `errors` and shows that instead.

The form also applies Azure's rule for an object name -- 1 to 127 characters of
letters, digits and dashes -- so a bad value never leaves the browser. The
message names the likely mistake: pasting the portal's Secret Identifier URI,
which carries a vault host and a pinned version, rather than the secret's name.

Validation runs against the trimmed value, so blanking the field still reads as
"clear the association" rather than as a malformed name. A pre-existing test
covering that clearing behaviour is what caught it.

Existing form-level guards already stop an invalid submit: the dialog disables
Save while the form is invalid, and submitConfiguration returns early.

Scoped to this form. ErrorHandlingService swallows the same `errors` block for
every other screen in Admin.UI, which is worth fixing on its own terms.

Claude-Session: https://claude.ai/code/session_01QoUHyt1ALkruCbuYxHSXiB
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds nullable vendor authentication settings with a validated signing-key secret ID. It persists and returns the settings through tenant APIs and queries. The Admin UI maps, validates, submits, and displays the setting, and removes vendor edit feature gating.

Changes

Vendor authentication support

Layer / File(s) Summary
Authentication contracts and persistence
DotNet/Shared/Application/Models/Tenant/*, DotNet/Tenant/Data/*, DotNet/Tenant/Migrations/*, DotNet/ServiceTests/UnitTests/Tenant/*
Adds VendorAuthenticationSettings, model properties, validation, JSON persistence, change tracking, migration support, and binding tests.
Vendor API persistence and query flow
DotNet/Tenant/Controllers/VendorController.cs, DotNet/Tenant/Business/{Managers,Queries}/*, DotNet/ServiceTests/IntegrationTests/Tenant/*
Passes authentication through create and update operations, preserves omitted settings, exposes settings in vendor queries, and adds integration coverage.
Admin UI contract, service, and form flow
Web/Admin.UI/src/app/{interfaces,services,components/vendor}/*, Web/Admin.UI/src/assets/app.config.json
Maps nested authentication payloads, validates secret IDs, submits create and update models, displays validation errors, updates service routes, and removes edit feature gating.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AdminUI
  participant VendorService
  participant VendorController
  participant VendorManager
  participant TenantDatabase
  AdminUI->>VendorService: submit vendor name and secretId
  VendorService->>VendorController: send nested authentication.signingKeySecretId
  VendorController->>VendorManager: create or update vendor
  VendorManager->>TenantDatabase: persist Authentication
  TenantDatabase-->>VendorManager: saved vendor
  VendorManager-->>VendorController: return Authentication
  VendorController-->>VendorService: return vendor model
  VendorService-->>AdminUI: map signingKeySecretId to secretId
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.53% 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
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the vendor screen change for adding a secret key field.
Description check ✅ Passed The description covers the changes and local testing, but it does not mark the completed unit tests or specify documentation updates.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch LEGLINK-620
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch LEGLINK-620

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

… LEGLINK-620

# Conflicts:
#	DotNet/Shared/Application/Models/Tenant/VendorAuthenticationSettings.cs

@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

🧹 Nitpick comments (1)
DotNet/ServiceTests/IntegrationTests/Tenant/VendorManagerTests.cs (1)

114-131: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test explicit signing-key secret ID clearing.

This test covers an omitted Authentication object. Add a test that updates with Authentication = new VendorAuthenticationSettings { SigningKeySecretId = null } and verifies that the persisted secret ID is null. This is the documented clear operation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DotNet/ServiceTests/IntegrationTests/Tenant/VendorManagerTests.cs` around
lines 114 - 131, Add a focused test alongside
UpdateVendor_WithoutAuthentication_LeavesTheConfiguredSecretIdIntact that
updates the vendor with Authentication set to VendorAuthenticationSettings whose
SigningKeySecretId is null, then reloads the persisted vendor and asserts its
secret ID is null. Preserve the existing setup and persistence verification
pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@DotNet/Tenant/Controllers/VendorController.cs`:
- Around line 139-140: Update the successful PUT response in VendorController to
return Accepted(updatedVendor) instead of Ok, and explicitly declare
StatusCodes.Status202Accepted while preserving the updated vendor payload.
- Around line 100-104: Update the LinkSdk vendor contract types
CreateVendorModel, UpdateVendorModel, VendorModel, and
VendorAuthenticationSettings to include authentication.SigningKeySecretId mapped
with JsonPropertyName("signingKeySecretId"), and ensure CreateVendorAsync and
UpdateVendorAsync serialize and expose the field consistently. Add serialization
tests covering the new property if these SDK contracts or methods have existing
test coverage.

---

Nitpick comments:
In `@DotNet/ServiceTests/IntegrationTests/Tenant/VendorManagerTests.cs`:
- Around line 114-131: Add a focused test alongside
UpdateVendor_WithoutAuthentication_LeavesTheConfiguredSecretIdIntact that
updates the vendor with Authentication set to VendorAuthenticationSettings whose
SigningKeySecretId is null, then reloads the persisted vendor and asserts its
secret ID is null. Preserve the existing setup and persistence verification
pattern.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6d7e7068-9ba4-478c-84a3-11a6799c5eb8

📥 Commits

Reviewing files that changed from the base of the PR and between 728bd30 and 02af528.

📒 Files selected for processing (31)
  • DotNet/ServiceTests/IntegrationTests/Tenant/VendorControllerTests.cs
  • DotNet/ServiceTests/IntegrationTests/Tenant/VendorManagerTests.cs
  • DotNet/ServiceTests/IntegrationTests/Tenant/VendorQueriesTests.cs
  • DotNet/ServiceTests/UnitTests/Tenant/VendorAuthenticationValidationTests.cs
  • DotNet/ServiceTests/UnitTests/Tenant/VendorModelBindingTests.cs
  • DotNet/Shared/Application/Models/Tenant/CreateVendorModel.cs
  • DotNet/Shared/Application/Models/Tenant/UpdateVendorModel.cs
  • DotNet/Shared/Application/Models/Tenant/VendorAuthenticationSettings.cs
  • DotNet/Shared/Application/Models/Tenant/VendorModel.cs
  • DotNet/Shared/Application/Models/Tenant/VendorVersionModel.cs
  • DotNet/Tenant/Business/Managers/VendorManager.cs
  • DotNet/Tenant/Business/Queries/VendorQueries.cs
  • DotNet/Tenant/Controllers/VendorController.cs
  • DotNet/Tenant/Data/Entities/Vendor.cs
  • DotNet/Tenant/Data/Repository/TenantDbContext.cs
  • DotNet/Tenant/Migrations/20260804215404_AddVendorAuthentication.Designer.cs
  • DotNet/Tenant/Migrations/20260804215404_AddVendorAuthentication.cs
  • DotNet/Tenant/Migrations/TenantDbContextModelSnapshot.cs
  • Web/Admin.UI/src/app/components/vendor/vendor-config-form/vendor-config-form.component.html
  • Web/Admin.UI/src/app/components/vendor/vendor-config-form/vendor-config-form.component.spec.ts
  • Web/Admin.UI/src/app/components/vendor/vendor-config-form/vendor-config-form.component.ts
  • Web/Admin.UI/src/app/components/vendor/vendor-dashboard/vendor-dashboard.component.html
  • Web/Admin.UI/src/app/components/vendor/vendor-dashboard/vendor-dashboard.component.spec.ts
  • Web/Admin.UI/src/app/components/vendor/vendor-dashboard/vendor-dashboard.component.ts
  • Web/Admin.UI/src/app/interfaces/tenant/vendor-interface.ts
  • Web/Admin.UI/src/app/interfaces/vendor/vendor-config-model.interface.ts
  • Web/Admin.UI/src/app/services/app-config.service.ts
  • Web/Admin.UI/src/app/services/gateway/vendor/vendor.service.spec.ts
  • Web/Admin.UI/src/app/services/gateway/vendor/vendor.service.ts
  • Web/Admin.UI/src/assets/app.config.json
  • docs/superpowers/specs/2026-08-03-vendor-signing-key-secret-id-design.md
💤 Files with no reviewable changes (4)
  • Web/Admin.UI/src/app/interfaces/vendor/vendor-config-model.interface.ts
  • Web/Admin.UI/src/assets/app.config.json
  • docs/superpowers/specs/2026-08-03-vendor-signing-key-secret-id-design.md
  • Web/Admin.UI/src/app/services/app-config.service.ts

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🧹 Nitpick comments (1)
DotNet/ServiceTests/IntegrationTests/Tenant/VendorManagerTests.cs (1)

114-131: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test explicit signing-key secret ID clearing.

This test covers an omitted Authentication object. Add a test that updates with Authentication = new VendorAuthenticationSettings { SigningKeySecretId = null } and verifies that the persisted secret ID is null. This is the documented clear operation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DotNet/ServiceTests/IntegrationTests/Tenant/VendorManagerTests.cs` around
lines 114 - 131, Add a focused test alongside
UpdateVendor_WithoutAuthentication_LeavesTheConfiguredSecretIdIntact that
updates the vendor with Authentication set to VendorAuthenticationSettings whose
SigningKeySecretId is null, then reloads the persisted vendor and asserts its
secret ID is null. Preserve the existing setup and persistence verification
pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@DotNet/Tenant/Controllers/VendorController.cs`:
- Around line 139-140: Update the successful PUT response in VendorController to
return Accepted(updatedVendor) instead of Ok, and explicitly declare
StatusCodes.Status202Accepted while preserving the updated vendor payload.
- Around line 100-104: Update the LinkSdk vendor contract types
CreateVendorModel, UpdateVendorModel, VendorModel, and
VendorAuthenticationSettings to include authentication.SigningKeySecretId mapped
with JsonPropertyName("signingKeySecretId"), and ensure CreateVendorAsync and
UpdateVendorAsync serialize and expose the field consistently. Add serialization
tests covering the new property if these SDK contracts or methods have existing
test coverage.

---

Nitpick comments:
In `@DotNet/ServiceTests/IntegrationTests/Tenant/VendorManagerTests.cs`:
- Around line 114-131: Add a focused test alongside
UpdateVendor_WithoutAuthentication_LeavesTheConfiguredSecretIdIntact that
updates the vendor with Authentication set to VendorAuthenticationSettings whose
SigningKeySecretId is null, then reloads the persisted vendor and asserts its
secret ID is null. Preserve the existing setup and persistence verification
pattern.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6d7e7068-9ba4-478c-84a3-11a6799c5eb8

📥 Commits

Reviewing files that changed from the base of the PR and between 728bd30 and 02af528.

📒 Files selected for processing (31)
  • DotNet/ServiceTests/IntegrationTests/Tenant/VendorControllerTests.cs
  • DotNet/ServiceTests/IntegrationTests/Tenant/VendorManagerTests.cs
  • DotNet/ServiceTests/IntegrationTests/Tenant/VendorQueriesTests.cs
  • DotNet/ServiceTests/UnitTests/Tenant/VendorAuthenticationValidationTests.cs
  • DotNet/ServiceTests/UnitTests/Tenant/VendorModelBindingTests.cs
  • DotNet/Shared/Application/Models/Tenant/CreateVendorModel.cs
  • DotNet/Shared/Application/Models/Tenant/UpdateVendorModel.cs
  • DotNet/Shared/Application/Models/Tenant/VendorAuthenticationSettings.cs
  • DotNet/Shared/Application/Models/Tenant/VendorModel.cs
  • DotNet/Shared/Application/Models/Tenant/VendorVersionModel.cs
  • DotNet/Tenant/Business/Managers/VendorManager.cs
  • DotNet/Tenant/Business/Queries/VendorQueries.cs
  • DotNet/Tenant/Controllers/VendorController.cs
  • DotNet/Tenant/Data/Entities/Vendor.cs
  • DotNet/Tenant/Data/Repository/TenantDbContext.cs
  • DotNet/Tenant/Migrations/20260804215404_AddVendorAuthentication.Designer.cs
  • DotNet/Tenant/Migrations/20260804215404_AddVendorAuthentication.cs
  • DotNet/Tenant/Migrations/TenantDbContextModelSnapshot.cs
  • Web/Admin.UI/src/app/components/vendor/vendor-config-form/vendor-config-form.component.html
  • Web/Admin.UI/src/app/components/vendor/vendor-config-form/vendor-config-form.component.spec.ts
  • Web/Admin.UI/src/app/components/vendor/vendor-config-form/vendor-config-form.component.ts
  • Web/Admin.UI/src/app/components/vendor/vendor-dashboard/vendor-dashboard.component.html
  • Web/Admin.UI/src/app/components/vendor/vendor-dashboard/vendor-dashboard.component.spec.ts
  • Web/Admin.UI/src/app/components/vendor/vendor-dashboard/vendor-dashboard.component.ts
  • Web/Admin.UI/src/app/interfaces/tenant/vendor-interface.ts
  • Web/Admin.UI/src/app/interfaces/vendor/vendor-config-model.interface.ts
  • Web/Admin.UI/src/app/services/app-config.service.ts
  • Web/Admin.UI/src/app/services/gateway/vendor/vendor.service.spec.ts
  • Web/Admin.UI/src/app/services/gateway/vendor/vendor.service.ts
  • Web/Admin.UI/src/assets/app.config.json
  • docs/superpowers/specs/2026-08-03-vendor-signing-key-secret-id-design.md
💤 Files with no reviewable changes (4)
  • Web/Admin.UI/src/app/interfaces/vendor/vendor-config-model.interface.ts
  • Web/Admin.UI/src/assets/app.config.json
  • docs/superpowers/specs/2026-08-03-vendor-signing-key-secret-id-design.md
  • Web/Admin.UI/src/app/services/app-config.service.ts
🛑 Comments failed to post (2)
DotNet/Tenant/Controllers/VendorController.cs (2)

100-104: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -HI -i 'link.*sdk|sdk.*link' . || true
rg -n -i -C 4 'Vendor(Authentication|Model)?|signingKeySecretId|/vendor' . \
  -g '*.cs' -g '*.ts'

Repository: lantanagroup/link-cloud

Length of output: 50380


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Candidate LinkSdk paths =="
git ls-files | grep -iE '([Ll]ink[Ss]dk|sdk)/|link.*sdk|sdk.*link' | head -200

echo
echo "== Files named LinkSdk or Link.Sdk =="
fd -HI 'link[.]sdk|linksdk|link_sdk|sdk[.]link|sdks?lock' . || true

echo
echo "== Package references to Link SDK =="
rg -n -i 'Linksdk|Link\.Sdk|link\.sdk|dotnet add package|PackageReference|projectReference' -g '*.csproj' -g '*.props' -g '*.targets' -g '*.ps' -g 'package.json' -g 'pnpm-lock.yaml' -g 'yarn.lock' -g 'package-lock.json' . || true

echo
echo "== Vendor controller relevant section =="
if [ -f DotNet/Tenant/Controllers/VendorController.cs ]; then
  wc -l DotNet/Tenant/Controllers/VendorController.cs
  sed -n '1,210p' DotNet/Tenant/Controllers/VendorController.cs | nl -ba
fi

echo
echo "== Vendor model definitions =="
rg -n -C 4 'class (Vendor|CreateVendor|UpdateVendor|.*Vendor.*Model)|interface (Vendor|CreateVendor|UpdateVendor)|record .*Vendor|class .*VendorAuth|signingKeySecretId' DotNet/Tenant Web/Admin.UI/src -g '*.cs' -g '*.ts' || true

Repository: lantanagroup/link-cloud

Length of output: 41078


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== LinkSdk project =="
cat -n DotNet/LinkSdk/LinkSdk.csproj

echo
echo "== LinkSdk files =="
find DashNet/LinkSdk -type f 2>/dev/null || find DotNet/LinkSdk -type f | sort

echo
echo "== Vendor mentions in LinkSdk =="
rg -n -i -C 4 'Vendor|CreateVendor|UpdateVendor|signingKeySecretId|/vendor|PostVendor|PutVendor' DotNet/LinkSdk || true

echo
echo "== Tenant vendor controller relevant section =="
sed -n '1,200p' DotNet/Tenant/Controllers/VendorController.cs

echo
echo "== Vendor model definitions in link-cloud =="
rg -n -C 4 'class (Vendor|CreateVendor|UpdateVendor|CreateVendorModel|UpdateVendorModel|Vendor.*Model)|interface .*Vendor|record .*Vendor|class .*VendorAuth|signingKeySecretId' DotNet Web/Admin.UI/src -g '*.cs' -g '*.ts' || true

Repository: lantanagroup/link-cloud

Length of output: 50379


Update the LinkSdk vendor contracts.

LinkSdk exposes CreateVendorAsync(), UpdateVendorAsync(), and response VendorModel, but CreateVendorModel, UpdateVendorModel, VendorModel, and VendorAuthenticationSettings need to include authentication.SigningKeySecretId and the corresponding JsonPropertyName("signingKeySecretId"); add serialization tests if the SDK adds or exercises those fields.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DotNet/Tenant/Controllers/VendorController.cs` around lines 100 - 104, Update
the LinkSdk vendor contract types CreateVendorModel, UpdateVendorModel,
VendorModel, and VendorAuthenticationSettings to include
authentication.SigningKeySecretId mapped with
JsonPropertyName("signingKeySecretId"), and ensure CreateVendorAsync and
UpdateVendorAsync serialize and expose the field consistently. Add serialization
tests covering the new property if these SDK contracts or methods have existing
test coverage.

Source: Path instructions


139-140: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Return 202 Accepted for a successful PUT.

This endpoint returns 200 OK on Line 143. Change the response to Accepted(updatedVendor) and declare StatusCodes.Status202Accepted.

As per coding guidelines, “PUT operations: ... return 202 on successful update.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DotNet/Tenant/Controllers/VendorController.cs` around lines 139 - 140, Update
the successful PUT response in VendorController to return
Accepted(updatedVendor) instead of Ok, and explicitly declare
StatusCodes.Status202Accepted while preserving the updated vendor payload.

Source: Coding guidelines

@arianamihailescu arianamihailescu changed the title LEGLINK-620 LEGLINK-620: secret-key-on-Vendors screen Aug 5, 2026
@arianamihailescu
arianamihailescu merged commit edbc3e7 into dev Aug 5, 2026
19 of 20 checks passed
@arianamihailescu
arianamihailescu deleted the LEGLINK-620 branch August 5, 2026 17:36
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