Skip to content

Refactor PromptModel to use semantic Reason objects instead of ra…#1652

Open
TheBlackBit wants to merge 1 commit intoopenwallet-foundation:mainfrom
TheBlackBit:refactor_prompt_model
Open

Refactor PromptModel to use semantic Reason objects instead of ra…#1652
TheBlackBit wants to merge 1 commit intoopenwallet-foundation:mainfrom
TheBlackBit:refactor_prompt_model

Conversation

@TheBlackBit
Copy link
Copy Markdown
Contributor

@TheBlackBit TheBlackBit commented Mar 21, 2026

Fixes #1651

Summary

Unified prompt flows to consistently use the app-configured PromptModel instead of fallback/default model instances.
Standardized prompt copy derivation to Reason -> toHumanReadable so title/subtitle are consistent across entry points and platforms.
Updated related docs/KDocs to reflect the current contract prompt UI text comes from human-readable reason conversion, not direct request fields.

  • Tests pass
  • Appropriate changes to README are included in PR

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the prompt system to use semantic Reason objects (converted via PromptModel.toHumanReadable) instead of passing user-visible title/subtitle directly, aiming to unify prompt copy and ensure flows consistently use the app-configured PromptModel.

Changes:

  • Updated passphrase + biometric prompt APIs and dialog models to carry Reason instead of raw UI strings.
  • Threaded toHumanReadable conversion into Compose/Web/iOS UIs and Swift wrappers so UI derives copy from Reason.
  • Updated test app configurations and several Android presentment entry points to use TestAppConfiguration.promptModel.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
samples/testapp/src/wasmJsMain/kotlin/org/multipaz/testapp/TestAppConfiguration.wasmJs.kt Adds app-specific toHumanReadable mapping and wires it into WebPromptModel.Builder.
samples/testapp/src/iosMain/kotlin/org/multipaz/testapp/TestAppConfiguration.ios.kt Adds app-specific toHumanReadable mapping and wires it into IosPromptModel.Builder.
samples/testapp/src/commonMain/kotlin/org/multipaz/testapp/TestAppConfiguration.kt Introduces expected appToHumanReadable(...) for platform-specific reason→copy conversion.
samples/testapp/src/androidMain/kotlin/org/multipaz/testapp/ui/ConsentPromptScreen.android.kt Switches presentment coroutine context and biometric prompt calls to use app prompt model + Reason.
samples/testapp/src/androidMain/kotlin/org/multipaz/testapp/TestAppUriSchemePresentmentActivity.kt Overrides base activity prompt model to reuse the app-configured Android prompt model.
samples/testapp/src/androidMain/kotlin/org/multipaz/testapp/TestAppMdocNdefService.kt Passes app-configured prompt model into NFC presentment settings.
samples/testapp/src/androidMain/kotlin/org/multipaz/testapp/TestAppCredentialManagerPresentmentActivity.kt Overrides base activity prompt model to reuse the app-configured Android prompt model.
samples/testapp/src/androidMain/kotlin/org/multipaz/testapp/TestAppConfiguration.android.kt Adds app-specific toHumanReadable mapping and wires it into AndroidPromptModel.Builder.
samples/SwiftTestApp/SwiftTestApp/PassphrasePromptScreen.swift Migrates Swift sample usage to pass ReasonHumanReadable instead of title/subtitle.
multipaz/src/commonTest/kotlin/org/multipaz/prompt/PromptModelTest.kt Updates tests to use Reason.HumanReadable and asserts through the new parameters shape.
multipaz/src/commonMain/kotlin/org/multipaz/securearea/software/SoftwareSecureArea.kt Switches passphrase prompting to pass Reason through instead of precomputed title/subtitle.
multipaz/src/commonMain/kotlin/org/multipaz/securearea/cloud/CloudSecureArea.kt Switches passphrase prompting to pass Reason through instead of precomputed title/subtitle.
multipaz/src/commonMain/kotlin/org/multipaz/prompt/PromptModelExt.kt Updates requestPassphrase extension signature to take Reason.
multipaz/src/commonMain/kotlin/org/multipaz/prompt/PassphrasePromptDialogModel.kt Changes PassphraseRequest to carry Reason instead of title/subtitle.
multipaz/src/androidMain/kotlin/org/multipaz/securearea/AndroidKeystoreDefaultKeyUnlockDataProvider.kt Updates biometric prompting to pass Reason instead of title/subtitle.
multipaz/src/androidMain/kotlin/org/multipaz/prompt/BiometricPromptDialogModel.kt Changes biometric prompt dialog state to carry Reason.
multipaz/src/androidMain/kotlin/org/multipaz/prompt/AndroidPromptModelExt.kt Updates showBiometricPrompt extension signature to take Reason.
multipaz-swift/Sources/MultipazSwift/PromptModelExt.swift Updates Swift wrapper requestPassphrase to accept Reason and adds a Kotlin→Swift toHumanReadable bridge.
multipaz-swift/Sources/MultipazSwift/PromptDialogs.swift Wires SwiftUI prompt dialogs to derive title/subtitle via the prompt model’s toHumanReadable.
multipaz-swift/Sources/MultipazSwift/PassphrasePromptDialog.swift Updates SwiftUI passphrase dialog to render title/subtitle from a computed human-readable reason.
multipaz-compose/src/webMain/kotlin/org/multipaz/compose/prompt/PromptDialogs.web.kt Passes a toHumanReadable lambda into the web passphrase dialog.
multipaz-compose/src/iosMain/kotlin/org/multipaz/compose/prompt/PromptDialogs.ios.kt Passes a toHumanReadable lambda into the iOS passphrase dialog.
multipaz-compose/src/commonMain/kotlin/org/multipaz/compose/prompt/PassphrasePromptDialog.kt Converts Reason→human-readable in the Compose passphrase dialog before rendering.
multipaz-compose/src/androidMain/kotlin/org/multipaz/compose/prompt/PromptDialogs.android.kt Wires Android Compose dialogs to call toHumanReadable for biometric + passphrase prompts.
multipaz-compose/src/androidMain/kotlin/org/multipaz/compose/prompt/BiometricPromptDialog.kt Converts Reason→human-readable before showing the platform biometric prompt.
multipaz-compose/src/androidMain/kotlin/org/multipaz/compose/presentment/UriSchemePresentmentActivity.kt Makes the activity prompt model overridable so apps can supply their configured instance.
multipaz-compose/src/androidMain/kotlin/org/multipaz/compose/digitalcredentials/CredentialManagerPresentmentActivity.kt Makes the activity prompt model overridable so apps can supply their configured instance.

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

@TheBlackBit TheBlackBit force-pushed the refactor_prompt_model branch 2 times, most recently from 3f27cfe to d488bc2 Compare April 6, 2026 21:59
@TheBlackBit TheBlackBit marked this pull request as ready for review April 6, 2026 23:47
@TheBlackBit TheBlackBit requested review from davidz25 and hanluOMH April 7, 2026 16:02
abstract suspend fun getSettings(): Settings

private val promptModel = AndroidPromptModel.Builder().apply { addCommonDialogs() }.build()
protected open val promptModel = AndroidPromptModel.Builder().apply { addCommonDialogs() }.build()
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.

Instead of having the app inject toHumanReadable() into the PromptModel - necessitating opening this up so an app can do this - wouldn't it be a lot easier if we just did it by changing PromptDialogs() to take a new parameter like this

@Composable
expect fun PromptDialogs(
    promptModel: PromptModel,
    imageLoader: ImageLoader? = null,
    maxHeight: Dp? = null,
    excludeTypes: List<PromptDialogModel.DialogType<*>> = emptyList(),
    toHumanReadable: suspend (unlockReason: Reason, passphraseConstraints: PassphraseConstraints?) = defaultToHumanReadable
)

where defaultToHumanReadable() is part of multipaz-compose and using translated strings. Same for the one in Swift. That way you wouldn't have to change TestApp at all, I think!

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.

(Btw, TestAppConfiguration.promptModel should probably be removed, it's confusing we still have it. It predates Platform.promptModel being a thing, which should be used instead. I just tried removing it locally and it worked fine. If you want to include deletion of this in your next upload I think it would help.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Will, do it thank you 👌🏽

@TheBlackBit TheBlackBit force-pushed the refactor_prompt_model branch from d488bc2 to f09ed49 Compare April 10, 2026 18:27
@TheBlackBit TheBlackBit requested a review from davidz25 April 10, 2026 18:28
…w strings.

This change migrates `BiometricPromptState` and `PassphraseRequest` to use a `Reason` object, allowing the UI layer to resolve human-readable titles and subtitles via `PromptModel.toHumanReadable`. This decoupling enables better localization and application-specific customization of security prompts.

Key changes:
- Updated `requestPassphrase` and `showBiometricPrompt` to accept a `Reason` parameter.
- Modified Compose and Swift UI components to asynchronously resolve `Reason` into `HumanReadable` text before display.
- Updated `AndroidKeystoreDefaultKeyUnlockDataProvider`, `CloudSecureArea`, and `SoftwareSecureArea` to pass semantic reasons instead of pre-formatted strings.
- Implemented `appToHumanReadable` in the Test App across Android, iOS, and Web platforms to handle custom string mapping.
- Adjusted `PromptModelTest` and `SwiftTestApp` to reflect the new API structure.
- Exposed `promptModel` in `CredentialManagerPresentmentActivity` and `UriSchemePresentmentActivity` to allow subclasses to provide custom implementations.

Signed-off-by: Ever Morales <ever.morales@koombea.com>
@TheBlackBit TheBlackBit force-pushed the refactor_prompt_model branch from f09ed49 to f41640e Compare April 10, 2026 18:31
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.

Refactor Prompt model

4 participants