Skip to content

feat(mediator): add opt-in did:prism support - #669

Open
yshyn-iohk wants to merge 10 commits into
mainfrom
agent/manager/mediator-did-prism-support
Open

feat(mediator): add opt-in did:prism support#669
yshyn-iohk wants to merge 10 commits into
mainfrom
agent/manager/mediator-did-prism-support

Conversation

@yshyn-iohk

Copy link
Copy Markdown
Contributor

Summary

  • add did-method-prism to mediator
  • support an explicit operator-supplied did + keyStore identity path
  • preserve the existing generated did:peer:2 startup path as the default fallback
  • wire a combined peer + prism resolver using MultiFallbackResolver
  • document DID_PRISM_RESOLVER and the compatibility-preserving configuration model
  • add tests for both legacy and explicit identity configuration paths

Why

Issue #488 asks for mediator support for DID PRISM while keeping DID Peer compatibility.

PR #507 showed the intended direction, but it introduced a breaking configuration change and is now stale against current main. This PR delivers the core DID PRISM support against current main without forcing existing deployments to migrate away from the current did:peer:2 startup flow.

Behavior

  • Existing deployments using KEY_AGREEMENT_*, KEY_AUTHENTICATION_*, and SERVICE_ENDPOINTS continue to work.
  • Operators can now supply an explicit DID and keyStore in config to use identities such as did:prism.
  • DID resolution now supports both peer and prism methods.

Validation

  • sbt -Dsbt.server.autostart=false -Dsbt.supershell=false 'mediator/compile'
  • sbt -Dsbt.server.autostart=false -Dsbt.supershell=false 'mediator/testOnly org.hyperledger.identus.mediator.MediatorConfigSpec'
  • sbt -Dsbt.server.autostart=false -Dsbt.supershell=false 'mediator/testOnly org.hyperledger.identus.mediator.protocols.DiscoverFeaturesExecuterSpec'

Follow-up

The remaining work for full issue closure is integration coverage for did:prism, especially around the short- and long-form URI DoD from #488.

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

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Integration Test Results

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

Results for commit 7db94a6. ± Comparison against base commit 61d5349.

♻️ This comment has been updated with latest results.

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

Copy link
Copy Markdown
Contributor

I would like to keep this integration as simple as possible. It seems that we are having a lot of stuff here.
We already have everything we needed in scala-did - as we see here #507

If anyone wants this for a concrete use case or a demo I will gladly finish and polish the other PR.

@yshyn-iohk

Copy link
Copy Markdown
Contributor Author

@FabioPinheiro, this PR is based on your one. I didn't know if anyone would pick up the feature.
I added the Neoprism to test the flows with the PRISM DID using the corresponding DID registrar and resolver (Neoprism). Adding the Neoprism required to upgrade protobufs to the canonical ones (copied from the Neoprism as well).
I also updated the docs about the PRISM DID support and confirmed Neoprism as the default and real PRISM DID service.
Also, I hardened the problem-report protocol for available corner cases related to the PRISM DID.
The e2e tests provide greater confidence that this feature will work properly on the Identus platform.

If you recommend using the new version of the scala-did to replace some contributions in this PR, let's do this.

What other proposals do you have?

@patextreme

patextreme commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

A few notes after digging into the code (and compiling it to verify):

🔴 Default PRISM resolver URL — please fix before merge

application.conf:38-39

didPrismResolver = "https://raw.githubusercontent.com/FabioPinheiro/prism-vdr/refs/heads/main/mainnet/diddoc"

Points at the mutable main branch of a personal fork via raw.githubusercontent.com — no pin, no integrity check, not SLA-backed. It's only hit when actually resolving a did:prism DID (a did:peer-only deployment never reaches it), but the moment any deployment encounters a did:prism DID it hits this unsafe default with no way to disable it.

Fix: official Identus-controlled resolver, or required-with-no-default. At minimum, document that operators must override DID_PRISM_RESOLVER for production.

🟡 Smaller things worth fixing here

  1. Config.Fallback masks bad config. It recovers from all errors, not just missing-data. A malformed did falls through to legacy with a confusing "missing endpoints/keyAgreement" error instead of "Fail to parse the DID." Only fall back on missing-data.
  2. Startup logs private keys. ZIO.log(s"MediatorConfig: $mediatorConfig") now logs keyStore.toString (private d values) at INFO. Redact or log just did + key kids/count.
  3. -Xfatal-warnings dropped for all tests. build.sbt:~220 — needed for ScalaPB, but relaxes the guard project-wide. Prefer @nowarn on the specific warning.

On the reflection-based test — it's fine, just brittle

It got flagged elsewhere as CI-breaking, but that's a false alarm. I compiled the actual sources and ran javap:

public ZIO ... org$hyperledger$identus$mediator$AgentExecutorMediator$$handleResolverFailure(Either, Transport, DidFail);

Since AgentExecutorMediator is a case class and handleResolverFailure is a private def in its body, Scala 3 mangles it to ...$$handleResolverFailure, so endsWith("$$handleResolverFailure") matches and the tests run (green CI confirms). The reflection is still brittle though — optional cleanup: make the method private[mediator] and call it directly from the test.

🟢 Nice-to-haves

  • MediatorPrismE2ESpec: assertResolves defined but never called; aliasIndex/createOperation populated but never read.
  • Title says "opt-in," but PRISM resolution is always on. Not necessarily wrong (a mediator arguably should resolve any DID method), just worth knowing. Optional: DID_PRISM_ENABLED=false to exclude the resolver.

TL;DR

Only the default resolver URL needs to land before merge. Everything else is polish.

@sonarqubecloud

Copy link
Copy Markdown

@yshyn-iohk
yshyn-iohk marked this pull request as ready for review July 22, 2026 13:26
@yshyn-iohk
yshyn-iohk requested a review from a team as a code owner July 22, 2026 13:26

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7db94a6d2a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +105 to +106
val config: Config[MediatorConfig] =
Config.Fallback(explicitConfig, legacyConfig)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject invalid explicit identity configuration

When an operator supplies an explicit did/keyStore but any field is missing or malformed, Config.Fallback retries the complete legacy configuration instead of reporting the error. In environments that still provide the legacy key variables—most notably the checked-in Docker Compose configuration—the mediator can therefore start under the legacy peer DID and keys rather than the configured PRISM identity, leaving clients addressing the configured DID unable to communicate and potentially activating the demo identity. Select the branch based on whether explicit identity fields are present, and propagate validation errors once that branch is selected.

AGENTS.md reference: AGENTS.md:L128-L130

Useful? React with 👍 / 👎.

Comment thread build.sbt
)
.settings((setupTestConfig): _*)
.settings(
Test / scalacOptions ~= (_.filterNot(_ == "-Xfatal-warnings")),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve fatal warnings for handwritten tests

This removes -Xfatal-warnings from the entire mediator test configuration merely to accommodate generated protobuf sources, so warnings in all handwritten tests will now pass locally and in CI. That bypasses the repository's documented no-warning quality gate; scope warning suppression to the managed ScalaPB output (or suppress its specific diagnostics) rather than disabling the gate for every test source.

AGENTS.md reference: AGENTS.md:L265-L270

Useful? React with 👍 / 👎.

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.

3 participants