Skip to content

refactor: domain-first module restructuring with DIDKeySigner, error standardization, and HTTP layer extraction#1719

Draft
yshyn-iohk wants to merge 50 commits intomainfrom
clause/1716
Draft

refactor: domain-first module restructuring with DIDKeySigner, error standardization, and HTTP layer extraction#1719
yshyn-iohk wants to merge 50 commits intomainfrom
clause/1716

Conversation

@yshyn-iohk
Copy link
Copy Markdown
Contributor

@yshyn-iohk yshyn-iohk commented Feb 26, 2026

Summary

Domain-first module restructuring of the cloud-agent codebase, improving separation of concerns, dependency hygiene, and architectural consistency.

Phase 1-14: Module Restructuring

  • Extracted domain modules: did/api, did/core, credentials/api, credentials/core, connections/api, connections/core, notifications/api, notifications/core, wallet-management/api, wallet-management/core
  • Extracted VDR subsystem: vdr/api, vdr/core, vdr/service, vdr/prism-node, vdr/database, vdr/memory, vdr/blockfrost, vdr/proxy
  • Extracted persistence modules: credentials/persistence-doobie, connections/persistence-doobie, wallet-management/persistence-doobie, wallet-management/secrets-vault
  • Created shared/predef for cross-cutting Scala predef customizations
  • Renamed config keys from legacy castor/pollux/connect/mercury to did/credentials/connections/didcomm

Phase 15: DIDKeySigner, Error Standardization, HTTP Layer Extraction

DIDKeySigner extraction:

  • Created DIDKeySigner trait in did/api module — generic key resolution abstraction
  • Implemented DIDKeySignerImpl in wallet-management/core using ManagedDIDService
  • Moved PrismNodeVdrOperationSigner from api-server to vdr/prism-node, refactored to depend on DIDKeySigner

Error handling standardization:

  • Migrated wallet-management errors (CreateManagedDIDError, GetManagedDIDError, PublishManagedDIDError, UpdateManagedDIDError) to extend Failure with proper HTTP status codes
  • Migrated EventNotificationServiceError to extend Failure
  • Removed manual given Conversion[XxxError, ErrorResponse] blocks from DIDRegistrarController

HTTP module extraction:

  • Created api-server-http-core module with shared HTTP infrastructure (19 files: ErrorResponse, EndpointOutputs, SecurityLogic, Authenticator, credentials types, etc.)
  • Created notifications-http module as pilot for domain HTTP separation (5 files: EventController, EventEndpoints, EventServerEndpoints, webhook DTOs)
  • Generalized EventServerEndpoints to use AuthenticatorWithAuthZ[BaseEntity] trait instead of concrete DefaultAuthenticator

Test plan

  • sbt compile — all modules compile cleanly
  • sbt scalafmtAll — formatting applied
  • vdrPrismNode/testOnly PrismNodeVdrOperationSignerSpec — 3/3 passed
  • walletManagement/test — 178 passed, 0 failed
  • notifications/test — 9/9 passed
  • apiServer/testOnly SecurityLogicSpec — 6/6 passed
  • Full CI validation

Generated with Claude Code

@yshyn-iohk yshyn-iohk requested a review from a team as a code owner February 26, 2026 19:17
@yshyn-iohk yshyn-iohk marked this pull request as draft February 26, 2026 19:17
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 26, 2026

Unit Test Results

0 files   - 113  0 suites   - 113   0s ⏱️ - 23m 48s
0 tests  - 925  0 ✅  - 916  0 💤  - 8  0 ❌  - 1 
0 runs   - 932  0 ✅  - 923  0 💤  - 8  0 ❌  - 1 

Results for commit e94d2d0. ± Comparison against base commit 47f646e.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 26, 2026

Integration Test Results (prism-node)

1 tests  ±0   1 ✅ ±0   2s ⏱️ ±0s
1 suites ±0   0 💤 ±0 
1 files   ±0   0 ❌ ±0 

Results for commit f1c46f6. ± Comparison against base commit ea1e14d.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 26, 2026

Integration Test Results

 23 files  ±0   23 suites  ±0   4s ⏱️ ±0s
 58 tests ±0   58 ✅ ±0  0 💤 ±0  0 ❌ ±0 
106 runs  ±0  106 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 550f48d. ± Comparison against base commit ea1e14d.

♻️ This comment has been updated with latest results.

@yshyn-iohk yshyn-iohk force-pushed the clause/1716 branch 3 times, most recently from 305677e to 12ec303 Compare February 28, 2026 18:13
Rename all modules, packages, config sections, and infrastructure from
internal codenames (mercury, pollux, castor, connect, agent.*) to
domain-first names (didcomm, credentials, did, connections, etc.)
following ADR 0001.

Changes include:
- Rename module directories from codenames to domain names
- Rename SBT project IDs, artifact names, and dependency objects
- Rename Scala packages throughout the codebase
- Rename agent.* packages (walletapi, server, notification, vdr)
- Move notification traits from core to API module
- Align event.notification package to notifications
- Rename config sections (pollux -> credentials, connect -> connections)
- Rename env vars (POLLUX_DB_* -> CREDENTIALS_DB_*, etc.)
- Rename SQL migration paths and Docker/Helm infrastructure
- Remove unused re-export package.scala files
- Remove stale codename build artifact directories
- Remove duplicate and dead code files
- Clean up import aliases and comments referencing old names
- Update .github/labeler.yml and CI workflow for new paths

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
- Extract DIDKeySigner trait to did/api module with DIDKeySignerImpl
  in wallet-management, decoupling key resolution from VDR operations
- Move PrismNodeVdrOperationSigner from api-server to vdr/prism-node,
  now depends on DIDKeySigner instead of ManagedDIDService
- Standardize wallet-management errors to extend Failure with proper
  HTTP status codes, removing manual Conversion blocks
- Create api-server-http-core module with shared HTTP infrastructure
  (ErrorResponse, EndpointOutputs, SecurityLogic, Authenticator, etc.)
- Create notifications-http module as pilot for domain HTTP separation
- Generalize EventServerEndpoints to use AuthenticatorWithAuthZ trait

Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
@yshyn-iohk yshyn-iohk changed the title [WIP] Issue 1716 refactored by Cursor refactor: domain-first module restructuring with DIDKeySigner, error standardization, and HTTP layer extraction Mar 2, 2026
yshyn-iohk and others added 17 commits March 2, 2026 19:39
Phase 16 of domain-first module restructuring:

- Generalize DefaultAuthenticator to AuthenticatorWithAuthZ[BaseEntity]
  in all 13 ServerEndpoints companion objects
- Extract 5 domain HTTP modules from api-server:
  credential-status-http, verification-http, vdr-http,
  connections-http, did-http (51 files moved)
- Refactor ConnectionControllerImpl to take URL instead of AppConfig
- Extract oid4vci-core module with IssuanceSession, Openid4VCIProofJwtOps,
  and IssuanceSessionStorage (3 files)
- Decompose BackgroundJobsHelper (247 lines) into focused traits:
  DIDResolutionHelper, JwtIssuerHelper, DIDCommHelper

Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
…coupling

Extract system-http, didcomm-http, credential-schema-http,
credential-definition-http, prex-http, oid4vci-http,
api-server-controller-commons, issue-http, and presentproof-http
from api-server/core (~90 files moved). Replace AppConfig dependencies
with domain-specific config case classes (IssueControllerConfig,
PresentProofControllerConfig, DIDCommControllerConfig,
CredentialIssuerControllerConfig). Extract FeatureFlagConfig and
PrismEnvelopeResponse to api-server-http-core. Reduces api-server/core
from ~149 to 64 files.

Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
Extract iam-core (authentication + authorization, 20 files),
iam-entity-http (10 files), and iam-wallet-http (6 files) from
api-server/core. Decouple config case classes (AdminConfig,
ApiKeyConfig, KeycloakConfig) from AppConfig by removing their
.layer companions and inlining derivation in Modules.scala.

Move SchemaRegistryServerEndpoints to credential-schema-http and
CredentialDefinitionRegistryServerEndpoints to credential-definition-http,
replacing AppConfig with serviceName: String parameter. Move
Oid4vciAuthenticator and CredentialIssuerServerEndpoints to oid4vci-http.

Reduces api-server/core from 64 to 24 files.

Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
…core

- Create api-server-config module with AppConfig.scala, breaking the
  circular dependency between apiServer and apiServerJobs
- Move VerificationConfig.toPresentationVerificationOptions() to
  PresentBackgroundJobs to remove VC-JWT/DID imports from config module
- Extract 10 background job files to api-server-jobs module with proper
  domain module dependencies
- Fix pre-existing test compilation failures (Phase 18 constructor
  changes, missing IssueControllerConfig layer, SystemControllerImpl
  version parameter)
- api-server/core reduced from 24 to 13 source files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…dpoints) to api-server-http-core

Split CustomServerInterceptors: tapir interceptors moved to http-core, http4s error
handler extracted to Http4sErrorHandler in api-server/core. Parameterized ZHttpEndpoints
to remove BuildInfo/DocModels dependencies before moving to http-core. api-server/core
now has 11 source files — the genuine assembly layer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove credentialsAnoncreds and didcommAgent from apiServer direct deps
(both transitive via apiServerJobs/didcommHttp). Add 16 architecture
constraints covering HTTP module isolation, infrastructure module
boundaries, and persistence/HTTP separation. Generate Phase 20
dependency graph snapshot (286 edges).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…dApi/didCore

Move 22 model types, service traits, error types, and utilities from didCore
to didApi, reversing the dependency so didCore depends on didApi. Only 3
service implementation files remain in didCore (PrismNodeDIDService,
NeoPrismDIDService, NeoPrismClient). Seven modules switched from didCore to
didApi, leaving only apiServer depending on didCore for wiring. This prevents
didCore's heavy gRPC/HTTP implementations from leaking to infrastructure modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…odules

Switch didcommHttp from connectionsCore+credentialsCore to
connectionsApi+credentialsApi, and connectionsHttp from connectionsCore
to connectionsApi. All needed types were already re-exported via API
modules. Add Direct-scope architecture constraints to prevent regression.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace credentialsCore's fat dependency on didcommAgentDidcommx (which
pulls in 13 protocol modules via didcommAgent) with direct dependencies
on only the specific protocols actually used: protocolIssueCredential and
protocolPresentProof. Move didcommAgentDidcommx to test-only scope and
remove unused didcommVC dependency entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Decompose the monolithic apiServerJobs (10 files, 11 deps) into 6 focused
modules: apiServerJobsCore (shared helpers), apiServerJobsConnect,
apiServerJobsIssue, apiServerJobsPresent, apiServerJobsStatusList, and
apiServerJobsDidSync. Each domain owns its background job handlers with
only the dependencies it actually needs. Add architecture constraints to
prevent cross-job module coupling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ok module

Move WebhookPublisher, WebhookPublisherError, and JsonEventEncoders from
api-server/core into modules/notifications/webhook to reduce api-server/core
scope and make webhook infrastructure dependencies explicit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace HTTP DTO imports with local webhook-specific DTOs in
JsonEventEncoders, removing dependencies on connectionsHttp, didHttp,
issueHttp, and presentProofHttp. Adds architecture constraints to
prevent re-introducing these dependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…maHttp

Switch CredentialDefinitionResponsePage to use its own local annotations
instead of importing from CredentialSchemaResponsePage. This also fixes
API docs showing schema-specific example URLs for credential definitions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move lightweight types (Entity, Wallet, GenericSecretStorage, EntityService,
EntityServiceError) into walletManagementApi and reverse the dependency so
walletManagement depends on walletManagementApi. Delete unused type alias
files (WalletManagementApi.scala, WalletManagementApiTestExports.scala).
This gives apiServerHttpCore a lighter transitive closure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mAgentDidcommx

Split PeerDID into data class (didcommModels) and factory/resolver logic
(PeerDIDCreation in didcommResolver). walletManagement now depends on the
much lighter didcommResolver instead of didcommAgentDidcommx, eliminating
a massive transitive closure of 13 protocol modules and the full didcommx
adapter from the wallet domain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move PresentationDefinition types and PresentationDefinitionValidator from
credentialsPreX into credentialsCore (same package, no import changes).
credentialsPreX now depends on credentialsCore instead of vice versa.
First step toward making credentialsCore abstract over credential formats.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move CompactFormat and ModelsExtensionMethods (pure data types) from
credentialsSDJWT to credentialsCore. Introduce SDJwtService trait in
credentialsCore with Ed25519PrivateKey parameters, replacing direct
SDJWT object calls and sdjwtwrapper-bound types (HolderPrivateKey,
IssuerPrivateKey). SDJwtServiceLive in credentialsSDJWT wraps the
existing SDJWT object and handles key conversions internally.

credentialsSDJWT now depends on credentialsCore instead of vice versa.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
yshyn-iohk and others added 29 commits March 4, 2026 12:44
- apiServerJobsCore: replace ES256KSigner/EdSigner with VcJwtService
- credentialsPreX: add JwtDecoder param to decouple from JwtCredential/JwtPresentation
- oid4vciCore: move JwtSignerImplicits to sharedCrypto
- oid4vciHttp: add explicit credentialsVcJWT dep (was transitive via oid4vciCore)
- Add arch constraints for apiServerJobsCore and oid4vciCore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…entialsCore

Type-erase at the consumer boundary by introducing JsonEventConsumer
in notificationsApi. WebhookPublisher now works with Seq[JsonEventConsumer]
instead of typed consumers. JsonEventEncoders moved to apiServer where
WebhookPublisherFactory wires typed consumers with domain-specific encoders.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Design for composable module architecture covering credential
(format, data model, builder, signer, verifier) and protocol
(transport, issuance, presentation, PEX) dimensions with
contract-based decoupling and incremental migration strategy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TDD-driven, phase-by-phase implementation plan for migrating to
composable plugin architecture. Phase 0 (foundation) and Phase 1
(leaf extraction) are fully detailed with exact file paths, test
code, and implementation code. Phases 2-5 are outlined at task level.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… module graph

- Add PersistenceProvider contract with PostgreSQL and SQLite modules
- Add SQLite considerations (no advisory locks, migration variants)
- Add DIDComm protocol versioning (v2/v3 as separate modules)
- Add Phase 5 (SQLite) to implementation plan, renumber Phase 6

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 0 of plugin architecture migration:
- Capability, Contract, Cardinality types for module dependency system
- Module trait with lifecycle, capabilities, per-module config
- ModuleRegistry with dependency validation and capability resolution
- Credential contracts: CredentialSigner, DataModelCodec, CredentialBuilder,
  VerificationCheck, RevocationCheck, CredentialVerifier combinator
- Protocol contracts: ProtocolTransport, IssuanceProtocol,
  PresentationProtocol, PresentationExchange
- 13 tests passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add zio-json to shared module dependencies. Replace String with
zio.json.ast.Json in all contract interfaces (BuildContext,
BuildState, BuiltCredential, ProtocolMessage, IssuanceProtocol,
PresentationProtocol, PresentationExchange, DataModelCodec).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract EdDSA and Secp256k1 CredentialSigner implementations from
vc-jwt module into sharedCrypto, and add JwtExpiryCheck as the first
VerificationCheck implementation in shared core.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Vcdm11DataModelCodec that encodes/decodes W3C VCDM 1.1 credential
structure. Add JwtCredentialBuilder that composes DataModelCodec +
CredentialSigner through a pipeline: encode claims → serialize →
sign → assemble JWT string.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Vcdm11DataModelCodec → credentialsCore (codec package)
- JwtExpiryCheck → credentialsCore (verification package)
- JwtCredentialBuilder → credentialsVcJWT

shared/credentials now contains only pure contract traits and
value types. All implementations live in their domain modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap existing components as Module implementations:
- EdDsaSignerModule, Secp256k1SignerModule (sharedCrypto)
- Vcdm11CodecModule (credentialsCore)
- JwtBuilderModule (credentialsVcJWT) — requires signer + codec

Integration test validates full dependency graph: registration,
resolution by contract/variant, and missing dependency detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Crypto primitives (EdDSA, secp256k1) are always-on infrastructure,
not pluggable modules. They remain as CredentialSigner implementations
but no longer wrapped in Module declarations. JwtBuilderModule no
longer requires CredentialSigner capability — signers are injected
directly as constructor dependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…se 3)

Add DIDCommIssuanceModule declaring IssuanceProtocol("didcomm-v3")
capability. Add DIDCommIssuanceAdapter that bridges the IssuanceProtocol
contract to the existing CredentialService — dispatches createRequest
and issueCredential to format-specific methods based on record's
credential format. Enables incremental migration via strangler fig
pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…(Phase 3.4)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add DIDCommV2 transport, OIDC transport, and PresentationExchange
module declarations. Extend ModuleRegistry integration tests to
cover issuance and presentation protocol resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ase 5)

- PersistenceProvider trait and PersistenceType enum in shared
- SqlitePersistenceProvider with Flyway migration support
- PostgresPersistenceModule and SqlitePersistenceModule declarations
- New persistence-sqlite sbt project with sqlite-jdbc dependency
- 9 tests: contract (2), SQLite provider (3), module registry (4)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ModuleRegistry.fromAll with disable filtering and report generation
- AllModules registry collecting all extracted modules
- CloudAgentApp validates module dependency graph at startup
- Integration tests expanded to 10 (covering all modules + filtering)
- ModuleRegistry unit tests expanded to 8

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enforce that shared contains only contracts (no implementation deps)
and persistence-sqlite stays isolated from domain modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bridges IssuanceProtocol contract to OID4VCI redirect-based flow.
Most methods are unsupported (OID4VCI uses HTTP, not messages),
but the adapter formalizes OID4VCI as a first-class protocol.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bridges PresentationProtocol contract to OID4VP redirect-based flow.
Registered in AllModules for startup validation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract SdJwtCredentialBuilder that delegates to SDJwtService for
credential issuance. Includes IssuerKeyResolver trait to bridge
generic KeyRef to Ed25519PrivateKey. Registered as SdJwtBuilderModule
in AllModules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract AnonCredsCredentialBuilder that delegates to AnoncredService
for credential issuance. Uses CredentialContext.Resolver to bridge
pre-negotiated state (cred def, offer, request) from the protocol
layer. Add zio-test dependencies to credentialsAnoncreds project.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move JWT and SD-JWT verification logic behind PresentationService,
SDJwtService, and VcJwtService abstractions so that apiServerJobsIssue
and apiServerJobsPresent no longer depend on credentialsVcJWT,
credentialsSDJWT, or credentialsAnoncreds modules directly.

BREAKING CHANGE: PresentationService, VcJwtService, and SDJwtService
traits have new methods that implementations must provide.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…yers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add abstract type member `Service` and abstract method `def layer: TaskLayer[Service]`
to the Module trait so modules can contribute ZIO service layers to the runtime.
Update all existing Module implementations with stub `type Service = Unit` and
`def layer = ZLayer.succeed(())`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
- Add credentialsVcJWT, credentialsSDJWT, credentialsAnoncreds as direct
  deps of apiServer (composition root needs access to all modules)
- Add arch constraints: shared must not depend on credentialsSDJWT or
  credentialsAnoncreds
- Remove unused CredentialBuilderRegistry import from AllModules
- Add implementation plan for wiring credential builders

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Mar 5, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
3 Security Hotspots
3.9% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant