From 1b0e6b5570856af2b2ad26f57c4a0daafb581233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ribo=CC=81?= Date: Sun, 13 Nov 2022 12:47:58 +0100 Subject: [PATCH] feat: integrate authenticate-sdk, buildSrc (Deps + Version globals), Protos and basic dependencies from old SDK --- authenticate-sdk/build.gradle.kts | 148 ++ .../src/androidMain/AndroidManifest.xml | 2 + .../src/androidMain/kotlin/authenticate.kt | 3 + .../src/androidMain/kotlin/createChallenge.kt | 3 + .../src/commonMain/kotlin/authenticate.kt | 1 + .../src/commonMain/kotlin/createChallenge.kt | 1 + .../src/jsMain/kotlin/authenticate.kt | 4 + .../src/jsMain/kotlin/createChallenge.kt | 5 + .../src/jvmMain/kotlin/authenticate.kt | 3 + .../src/jvmMain/kotlin/createChallenge.kt | 3 + build.gradle.kts | 39 +- buildSrc/build.gradle.kts | 9 + buildSrc/src/main/kotlin/Deps.kt | 30 + buildSrc/src/main/kotlin/PluginVersions.kt | 14 + buildSrc/src/main/kotlin/Plugins.kt | 15 + buildSrc/src/main/kotlin/Versions.kt | 30 + core-sdk/build.gradle.kts | 2 +- core-sdk/core_sdk.podspec | 4 +- protosLib/build.gradle.kts | 83 + protosLib/src/main/proto/common_models.proto | 108 ++ protosLib/src/main/proto/connector_api.proto | 443 +++++ .../src/main/proto/connector_models.proto | 90 + protosLib/src/main/proto/console_api.proto | 1481 +++++++++++++++++ protosLib/src/main/proto/console_models.proto | 244 +++ .../src/main/proto/credential_models.proto | 76 + protosLib/src/main/proto/cviews_api.proto | 21 + protosLib/src/main/proto/cviews_models.proto | 17 + protosLib/src/main/proto/health.proto | 63 + .../src/main/proto/intdemo/intdemo_api.proto | 57 + .../main/proto/intdemo/intdemo_models.proto | 17 + protosLib/src/main/proto/node_api.proto | 376 +++++ protosLib/src/main/proto/node_internal.proto | 30 + protosLib/src/main/proto/node_models.proto | 247 +++ protosLib/src/main/proto/package.json | 10 + .../src/main/proto/resources/markdown.tmpl | 95 ++ protosLib/src/main/proto/status.proto | 47 + settings.gradle.kts | 38 +- wallet-sdk/build.gradle.kts | 2 +- .../src/androidMain/AndroidManifest.xml | 2 + wallet-sdk/wallet_sdk.podspec | 4 +- 40 files changed, 3854 insertions(+), 13 deletions(-) create mode 100644 authenticate-sdk/build.gradle.kts create mode 100644 authenticate-sdk/src/androidMain/AndroidManifest.xml create mode 100644 authenticate-sdk/src/androidMain/kotlin/authenticate.kt create mode 100644 authenticate-sdk/src/androidMain/kotlin/createChallenge.kt create mode 100644 authenticate-sdk/src/commonMain/kotlin/authenticate.kt create mode 100644 authenticate-sdk/src/commonMain/kotlin/createChallenge.kt create mode 100644 authenticate-sdk/src/jsMain/kotlin/authenticate.kt create mode 100644 authenticate-sdk/src/jsMain/kotlin/createChallenge.kt create mode 100644 authenticate-sdk/src/jvmMain/kotlin/authenticate.kt create mode 100644 authenticate-sdk/src/jvmMain/kotlin/createChallenge.kt create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/src/main/kotlin/Deps.kt create mode 100644 buildSrc/src/main/kotlin/PluginVersions.kt create mode 100644 buildSrc/src/main/kotlin/Plugins.kt create mode 100644 buildSrc/src/main/kotlin/Versions.kt create mode 100644 protosLib/build.gradle.kts create mode 100644 protosLib/src/main/proto/common_models.proto create mode 100644 protosLib/src/main/proto/connector_api.proto create mode 100644 protosLib/src/main/proto/connector_models.proto create mode 100644 protosLib/src/main/proto/console_api.proto create mode 100644 protosLib/src/main/proto/console_models.proto create mode 100644 protosLib/src/main/proto/credential_models.proto create mode 100644 protosLib/src/main/proto/cviews_api.proto create mode 100644 protosLib/src/main/proto/cviews_models.proto create mode 100644 protosLib/src/main/proto/health.proto create mode 100755 protosLib/src/main/proto/intdemo/intdemo_api.proto create mode 100644 protosLib/src/main/proto/intdemo/intdemo_models.proto create mode 100644 protosLib/src/main/proto/node_api.proto create mode 100644 protosLib/src/main/proto/node_internal.proto create mode 100644 protosLib/src/main/proto/node_models.proto create mode 100644 protosLib/src/main/proto/package.json create mode 100644 protosLib/src/main/proto/resources/markdown.tmpl create mode 100644 protosLib/src/main/proto/status.proto create mode 100644 wallet-sdk/src/androidMain/AndroidManifest.xml diff --git a/authenticate-sdk/build.gradle.kts b/authenticate-sdk/build.gradle.kts new file mode 100644 index 000000000..805e27478 --- /dev/null +++ b/authenticate-sdk/build.gradle.kts @@ -0,0 +1,148 @@ +import org.gradle.internal.os.OperatingSystem +import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackOutput.Target + +version = rootProject.version +val currentModuleName: String = "authenticate_sdk" +val os: OperatingSystem = OperatingSystem.current() + +plugins { + kotlin("multiplatform") + id("com.android.library") + id("org.jetbrains.dokka") +} + +kotlin { + android { + publishAllLibraryVariants() + } + jvm { + compilations.all { + kotlinOptions { + jvmTarget = "11" + } + } + testRuns["test"].executionTask.configure { + useJUnitPlatform() + } + } + + js(IR) { + this.moduleName = currentModuleName + this.binaries.library() + this.useCommonJs() + this.compilations["main"].packageJson { + this.version = rootProject.version.toString() + } + this.compilations["test"].packageJson { + this.version = rootProject.version.toString() + } + browser { + this.webpackTask { + this.output.library = currentModuleName + this.output.libraryTarget = Target.VAR + } + this.commonWebpackConfig { + this.cssSupport { + this.enabled = true + } + } + this.testTask { + this.useKarma { + this.useChromeHeadless() + } + } + } + nodejs { + this.testTask { + this.useKarma { + this.useChromeHeadless() + } + } + } + } + + + sourceSets { + val commonMain by getting { + dependencies { + implementation("com.benasher44:uuid:0.3.0") + implementation(project(":core-sdk")) + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test")) + } + } + val jvmMain by getting + val jvmTest by getting { + dependencies { + implementation("junit:junit:4.13.2") + } + } + val androidMain by getting + val androidTest by getting { + dependencies { + implementation("junit:junit:4.13.2") + } + } + val jsMain by getting + val jsTest by getting + + all { + languageSettings.optIn("kotlin.RequiresOptIn") + } + } +} + +android { + compileSdk = 32 + sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + defaultConfig { + minSdk = 21 + targetSdk = 32 + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + /** + * Because Software Components will not be created automatically for Maven publishing from + * Android Gradle Plugin 8.0. To opt-in to the future behavior, set the Gradle property android. + * disableAutomaticComponentCreation=true in the `gradle.properties` file or use the new + * publishing DSL. + */ + publishing { + multipleVariants { + withSourcesJar() + withJavadocJar() + allVariants() + } + } +} + +// Dokka implementation +tasks.withType { + moduleName.set(project.name) + moduleVersion.set(rootProject.version.toString()) + description = """ + This is a Kotlin Multiplatform Wallet-SDK Library + """.trimIndent() + dokkaSourceSets { + // TODO: Figure out how to include files to the documentations + named("commonMain") { + includes.from("Module.md", "docs/Module.md") + } + } +} + +// afterEvaluate { +// tasks.withType { +// testLogging { +// events("passed", "skipped", "failed", "standard_out", "standard_error") +// showExceptions = true +// showStackTraces = true +// } +// } +// } \ No newline at end of file diff --git a/authenticate-sdk/src/androidMain/AndroidManifest.xml b/authenticate-sdk/src/androidMain/AndroidManifest.xml new file mode 100644 index 000000000..7e4dcbacb --- /dev/null +++ b/authenticate-sdk/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/authenticate-sdk/src/androidMain/kotlin/authenticate.kt b/authenticate-sdk/src/androidMain/kotlin/authenticate.kt new file mode 100644 index 000000000..1960c88f9 --- /dev/null +++ b/authenticate-sdk/src/androidMain/kotlin/authenticate.kt @@ -0,0 +1,3 @@ +actual fun authenticate(did: String, signature: String, originalText: String):String { + return "hola"; +} diff --git a/authenticate-sdk/src/androidMain/kotlin/createChallenge.kt b/authenticate-sdk/src/androidMain/kotlin/createChallenge.kt new file mode 100644 index 000000000..2eab196d8 --- /dev/null +++ b/authenticate-sdk/src/androidMain/kotlin/createChallenge.kt @@ -0,0 +1,3 @@ +actual fun createChallenge(expiration: Int): String { + return "hola"; +} \ No newline at end of file diff --git a/authenticate-sdk/src/commonMain/kotlin/authenticate.kt b/authenticate-sdk/src/commonMain/kotlin/authenticate.kt new file mode 100644 index 000000000..01b6b0481 --- /dev/null +++ b/authenticate-sdk/src/commonMain/kotlin/authenticate.kt @@ -0,0 +1 @@ +expect fun authenticate(did: String, signature: String, originalText: String):String diff --git a/authenticate-sdk/src/commonMain/kotlin/createChallenge.kt b/authenticate-sdk/src/commonMain/kotlin/createChallenge.kt new file mode 100644 index 000000000..4c268ae48 --- /dev/null +++ b/authenticate-sdk/src/commonMain/kotlin/createChallenge.kt @@ -0,0 +1 @@ +expect fun createChallenge(expiration: Int): String \ No newline at end of file diff --git a/authenticate-sdk/src/jsMain/kotlin/authenticate.kt b/authenticate-sdk/src/jsMain/kotlin/authenticate.kt new file mode 100644 index 000000000..8d89e415c --- /dev/null +++ b/authenticate-sdk/src/jsMain/kotlin/authenticate.kt @@ -0,0 +1,4 @@ +@JsExport +actual fun authenticate(did: String, signature: String, originalText: String):String { + return "hola"; +} diff --git a/authenticate-sdk/src/jsMain/kotlin/createChallenge.kt b/authenticate-sdk/src/jsMain/kotlin/createChallenge.kt new file mode 100644 index 000000000..e83348369 --- /dev/null +++ b/authenticate-sdk/src/jsMain/kotlin/createChallenge.kt @@ -0,0 +1,5 @@ + +@JsExport +actual fun createChallenge(expiration: Int): String { + return "hola"; +} \ No newline at end of file diff --git a/authenticate-sdk/src/jvmMain/kotlin/authenticate.kt b/authenticate-sdk/src/jvmMain/kotlin/authenticate.kt new file mode 100644 index 000000000..1960c88f9 --- /dev/null +++ b/authenticate-sdk/src/jvmMain/kotlin/authenticate.kt @@ -0,0 +1,3 @@ +actual fun authenticate(did: String, signature: String, originalText: String):String { + return "hola"; +} diff --git a/authenticate-sdk/src/jvmMain/kotlin/createChallenge.kt b/authenticate-sdk/src/jvmMain/kotlin/createChallenge.kt new file mode 100644 index 000000000..2eab196d8 --- /dev/null +++ b/authenticate-sdk/src/jvmMain/kotlin/createChallenge.kt @@ -0,0 +1,3 @@ +actual fun createChallenge(expiration: Int): String { + return "hola"; +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 275d65b19..668844023 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,17 +1,38 @@ import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + vendor.set(JvmVendorSpec.ADOPTOPENJDK) + } +} + plugins { - id("maven-publish") - id("org.jetbrains.dokka") version "1.7.10" - id("org.jlleitschuh.gradle.ktlint") version "11.0.0" + java + kotlin(Plugins.multiplatform) version PluginVersions.multiplatform apply false + kotlin(Plugins.serialization) version PluginVersions.multiplatform apply false + id(Plugins.protobuf) version PluginVersions.protobuf apply false + id(Plugins.npmPublish) version PluginVersions.npmPublish apply false + id(Plugins.gitVersion) version PluginVersions.gitVersion + id(Plugins.klint) version PluginVersions.klint + id(Plugins.compatibilityValidator) version PluginVersions.compatibilityValidator + id(Plugins.gitOps) version PluginVersions.gitOps + id(Plugins.koverage) version PluginVersions.koverage + id(Plugins.dokka) version PluginVersions.dokka + `maven-publish` } buildscript { repositories { - gradlePluginPortal() - google() mavenCentral() + mavenLocal() + google() + maven("https://plugins.gradle.org/m2/") + // Needed for Kotlin coroutines that support new memory management mode + maven { + url = uri("https://maven.pkg.jetbrains.space/public/p/kotlinx-coroutines/maven") + } } dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20") @@ -24,8 +45,14 @@ group = "io.iohk.atala.prism" allprojects { repositories { - google() mavenCentral() + mavenLocal() + google() + maven("https://plugins.gradle.org/m2/") + // Needed for Kotlin coroutines that support new memory management mode + maven { + url = uri("https://maven.pkg.jetbrains.space/public/p/kotlinx-coroutines/maven") + } } // apply(plugin = "org.gradle.maven-publish") diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 000000000..181a98709 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,9 @@ +import org.gradle.kotlin.dsl.`kotlin-dsl` + +plugins { + `kotlin-dsl` +} + +repositories { + mavenCentral() +} diff --git a/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/src/main/kotlin/Deps.kt new file mode 100644 index 000000000..5e02fb8af --- /dev/null +++ b/buildSrc/src/main/kotlin/Deps.kt @@ -0,0 +1,30 @@ +object Deps { + const val kotlinSerializationJson = "org.jetbrains.kotlinx:kotlinx-serialization-json:${Versions.kotlinSerializationJson}" + const val kotlinBignum = "com.ionspin.kotlin:bignum:${Versions.kotlinBignum}" + const val kotlinCoroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinCoroutines}" + const val kotlinCoroutinesJDK8 = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:${Versions.kotlinCoroutinesJDK8}" + const val kotlinNodejs = "org.jetbrains.kotlinx:kotlinx-nodejs:${Versions.kotlinNodejs}" + const val kotlinDatetime = "org.jetbrains.kotlinx:kotlinx-datetime:${Versions.kotlinDatetime}" + const val grpcKotlinStub = "io.grpc:grpc-kotlin-stub:${Versions.grpcKotlinStub}" + const val grpcKotlinOkhttp = "io.grpc:grpc-okhttp:${Versions.grpcKotlinOkhttp}" + + const val bitcoinj = "org.bitcoinj:bitcoinj-core:${Versions.bitcoinj}" + const val bitcoinKmp = "fr.acinq.bitcoin:bitcoin-kmp:${Versions.bitcoinKmp}" + + const val pbandkRuntime = "io.iohk:pbandk-runtime:${Versions.pbandk}" + const val pbandkProtocGen = "io.iohk:protoc-gen-pbandk-lib-jvm:${Versions.pbandk}" + // NOTE: this adds Kotlin interop with some of the jvm8 features (e.g. CompletableFuture). + const val pbandkProtocGenJDK8 = "io.iohk:protoc-gen-pbandk-jvm:${Versions.pbandk}:jvm8@jar" + const val pbandkPrismClientsGenerator = "io.iohk.atala:pbandk-prism-clients-generator:${Versions.pbandk}" + + const val protobufJava = "com.google.protobuf:protobuf-java:${Versions.protobuf}" + const val protobufProtoc = "com.google.protobuf:protoc:${Versions.protobuf}" + const val protobufLite = "io.grpc:grpc-protobuf-lite:${Versions.protobufLite}" + + const val betterParse = "com.github.h0tk3y.betterParse:better-parse:${Versions.betterParse}" + const val krypto = "com.soywiz.korlibs.krypto:krypto:${Versions.krypto}" + const val guava = "com.google.guava:guava:${Versions.guava}" + const val spongyCastle = "com.madgag.spongycastle:prov:${Versions.spongyCastle}" + const val bouncyCastle = "org.bouncycastle:bcprov-jdk15on:${Versions.bouncyCastle}" + const val uuid = "com.benasher44:uuid:${Versions.uuid}" +} diff --git a/buildSrc/src/main/kotlin/PluginVersions.kt b/buildSrc/src/main/kotlin/PluginVersions.kt new file mode 100644 index 000000000..c64b89032 --- /dev/null +++ b/buildSrc/src/main/kotlin/PluginVersions.kt @@ -0,0 +1,14 @@ +object PluginVersions { + const val multiplatform = "1.6.0" + const val androidLibrary = "4.1.2" + const val protobuf = "0.8.14" + const val npmPublish = "2.0.2" + const val gitVersion = "0.12.3" + const val klint = "10.0.0" + const val multiplatformSwift = "2.0.3" + const val kfcDefinitions = "4.32.0" + const val compatibilityValidator = "0.8.0-RC" + const val gitOps = "5.0.0-rc.3" + const val koverage = "0.5.0" + const val dokka = "1.7.0" +} diff --git a/buildSrc/src/main/kotlin/Plugins.kt b/buildSrc/src/main/kotlin/Plugins.kt new file mode 100644 index 000000000..657d5ae5e --- /dev/null +++ b/buildSrc/src/main/kotlin/Plugins.kt @@ -0,0 +1,15 @@ +object Plugins { + const val multiplatform = "multiplatform" + const val serialization = "plugin.serialization" + const val androidLibrary = "com.android.library" + const val protobuf = "com.google.protobuf" + const val npmPublish = "dev.petuska.npm.publish" + const val gitVersion = "com.palantir.git-version" + const val klint = "org.jlleitschuh.gradle.ktlint" + const val multiplatformSwift = "com.chromaticnoise.multiplatform-swiftpackage" + const val kfcDefinitions = "com.github.turansky.kfc.definitions" + const val compatibilityValidator = "org.jetbrains.kotlinx.binary-compatibility-validator" + const val gitOps = "org.ajoberstar.grgit" + const val koverage = "org.jetbrains.kotlinx.kover" + const val dokka = "org.jetbrains.dokka" +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt new file mode 100644 index 000000000..f50b347ad --- /dev/null +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -0,0 +1,30 @@ +object Versions { + const val jvmTarget = "11" + const val iosTarget = "13" + const val androidTargetSdk = 29 + const val androidMinSdk = 26 + + const val kotlinSerializationJson = "1.3.0" + const val kotlinBignum = "0.3.1" + const val kotlinCoroutines = "1.5.1-new-mm-dev2" + const val kotlinCoroutinesJDK8 = "1.5.2" + const val kotlinNodejs = "0.0.7" + const val kotlinDatetime = "0.2.1" + const val grpcKotlinStub = "1.0.0" + const val grpcKotlinOkhttp = "1.36.0" + + const val bitcoinj = "0.15.10" + const val bitcoinKmp = "0.7.0" + + const val pbandk = "0.20.7" + const val protobuf = "3.12.0" + const val protobufLite = "1.36.0" + + const val swiftTools = "5.3" + const val betterParse = "0.4.3" + const val krypto = "2.4.12" + const val guava = "30.1-jre" + const val spongyCastle = "1.58.0.0" + const val bouncyCastle = "1.68" + const val uuid = "0.3.0" +} diff --git a/core-sdk/build.gradle.kts b/core-sdk/build.gradle.kts index 518586b6c..196146a3a 100644 --- a/core-sdk/build.gradle.kts +++ b/core-sdk/build.gradle.kts @@ -3,7 +3,7 @@ import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackOutput.Target version = rootProject.version -val currentModuleName: String = "wallet-core-sdk" +val currentModuleName: String = "wallet_core_sdk" val os: OperatingSystem = OperatingSystem.current() plugins { diff --git a/core-sdk/core_sdk.podspec b/core-sdk/core_sdk.podspec index 3f27f1b9a..d7c7278d3 100644 --- a/core-sdk/core_sdk.podspec +++ b/core-sdk/core_sdk.podspec @@ -6,7 +6,7 @@ Pod::Spec.new do |spec| spec.authors = 'IOG' spec.license = '' spec.summary = 'Wallet-Core-SDK' - spec.vendored_frameworks = 'build/cocoapods/framework/wallet-core-sdk.framework' + spec.vendored_frameworks = 'build/cocoapods/framework/wallet_core_sdk.framework' spec.libraries = 'c++' spec.ios.deployment_target = '13.0' spec.osx.deployment_target = '12.0' @@ -16,7 +16,7 @@ Pod::Spec.new do |spec| spec.pod_target_xcconfig = { 'KOTLIN_PROJECT_PATH' => ':core-sdk', - 'PRODUCT_MODULE_NAME' => 'wallet-core-sdk', + 'PRODUCT_MODULE_NAME' => 'wallet_core_sdk', } spec.script_phases = [ diff --git a/protosLib/build.gradle.kts b/protosLib/build.gradle.kts new file mode 100644 index 000000000..b92a590b5 --- /dev/null +++ b/protosLib/build.gradle.kts @@ -0,0 +1,83 @@ +import com.google.protobuf.gradle.* +import org.apache.tools.ant.taskdefs.condition.Os + +plugins { + `java-library` + id(Plugins.protobuf) +} + +// Mock configuration which derives compile only. +// Needed to resolve jar files of the dependency +val jarPathConf by configurations.creating { + extendsFrom(configurations.compileOnly.get()) +} + +dependencies { + jarPathConf(Deps.pbandkPrismClientsGenerator) + + // This is needed for includes, ref: https://github.com/google/protobuf-gradle-plugin/issues/41#issuecomment-143884188 + compileOnly(Deps.protobufJava) +} + +sourceSets { + main { + proto { + setSrcDirs(listOf("src/main/proto")) + setIncludes( + listOf( + "common_*.proto", + "node_*.proto", + "connector_*.proto", + "console_*.proto", + "status.proto", + "credential_*.proto" + ) + ) + } + } +} + +protobuf { + protoc { + artifact = if (Os.isFamily(Os.FAMILY_MAC)) { + if (System.getProperty("os.arch") != "x86_64") { + // In case of macOS and M1 chip then we need to use a different version of protobuf that support M1 chip arch + "${Deps.protobufProtoc}:osx-x86_64" // "com.google.protobuf:protoc:3.12.0:osx-x86_64" + } else { + Deps.protobufProtoc + } + } else { + Deps.protobufProtoc + } + } + plugins { + id("kotlin") { + artifact = Deps.pbandkProtocGenJDK8 + } + } + + val pbandkClientsGeneratorJar = configurations["jarPathConf"].files(configurations["jarPathConf"].dependencies.first()).first() + + generateProtoTasks { + ofSourceSet("main").forEach { task -> + task.builtins { + remove("java") + } + task.plugins { + id("kotlin") { + option("kotlin_package=io.iohk.atala.prism.protos") + option("kotlin_service_gen=$pbandkClientsGeneratorJar|io.iohk.atala.prism.generator.Generator") + option("visibility=public") + option("js_export=true") + option("with_annotations=@io.iohk.atala.prism.common.PrismSdkInternal") + } + } + } + } +} + +tasks { + compileJava { + enabled = false + } +} diff --git a/protosLib/src/main/proto/common_models.proto b/protosLib/src/main/proto/common_models.proto new file mode 100644 index 000000000..dcb5fe568 --- /dev/null +++ b/protosLib/src/main/proto/common_models.proto @@ -0,0 +1,108 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +package io.iohk.atala.prism.protos; + +import "google/protobuf/timestamp.proto"; + +/** + * A request that can be used to check service health. + * All PRISM services expose an RPC that accepts this message as request. + */ +message HealthCheckRequest {} + +/** + * A response that represents service health. + * Status code 0 with empty response represents a healthy and reachable service, + * while all other status codes represent issues with the service. + */ +message HealthCheckResponse {} + +/** + * Represents a date by its parts (day, month, year). + */ +message Date { + int32 year = 1; // A positive value. + int32 month = 2; // A value in the [1, 12] range. + int32 day = 3; // A value in the [1, 31] range (depending on the month, the maximum value might be 28). +} + +/** + * Represents a time interval between two given timestamps. + * The message represents a closed interval (i.e. both ends are inclusive and mandatory). + */ +message TimeInterval { + /** + * The starting timestamp. + * start_timestamp must be before or equal to end_timestamp. + */ + google.protobuf.Timestamp start_timestamp = 1; + /** + * The ending timestamp. + * end_timestamp must be after or equal to start_timestamp. + */ + google.protobuf.Timestamp end_timestamp = 2; +} + +/** + * This enum provides a way for some RPC requests to specify the direction so that the response values are sorted + * the way you want them to. + * Note that it specifies the direction only and doesn't say anything about a comparator + * (e.g. natural order, some RPC-specific order etc). + */ +enum SortByDirection { + SORT_BY_DIRECTION_UNKNOWN = 0; // Nothing provided, each API can define whether to fail or take a default value (commonly ASCENDING). + SORT_BY_DIRECTION_ASCENDING = 1; // Sort the results in ascending order. + SORT_BY_DIRECTION_DESCENDING = 2; // Sort the results in descending order. +} + +/** + * The supported ledger types. Specifies which chain is used for storing transactions. + */ +enum Ledger { + reserved 2; // Removed BITCOIN_TESTNET + reserved "BITCOIN_TESTNET"; + reserved 3; // Removed BITCOIN_MAINNET + reserved "BITCOIN_MAINNET"; + + UNKNOWN_LEDGER = 0; // Invalid default value. + IN_MEMORY = 1; // Store transactions in memory instead of blockchain, used only for development. + CARDANO_TESTNET = 4; // Cardano testnet, used for testing. + CARDANO_MAINNET = 5; // Cardano mainnet, used in production. +} + +/** + * Information about a ledger block. + * See Ledger documentation for details on which ledgers are possible. + */ +message BlockInfo { + reserved 2; // Removed timestamp_deprecated field + reserved "timestamp_deprecated"; + + int32 number = 1; // Number of the block in the ledger. + int32 index = 3; // Index of the transaction within the block. + google.protobuf.Timestamp timestamp = 4; // Timestamp when the block was created. +} + +/** + * Information about a ledger transaction and the block that the transaction is included in. + */ +message TransactionInfo { + string transaction_id = 1; // Transaction ID. + Ledger ledger = 2; // Ledger the transaction was published to. + BlockInfo block = 3; // Block the transaction was included in. +} + +/** + * The status of an Atala operation. + */ +enum OperationStatus { + UNKNOWN_OPERATION = 0; // The operation hasn't been received by the node service yet. + PENDING_SUBMISSION = 1; // The transaction containing this operation hasn't been published to the chain yet. + AWAIT_CONFIRMATION = 2; // The transaction containing this operation has been published to the chain, but hasn't been processed by PRISM yet. + CONFIRMED_AND_APPLIED = 3; // The operation has been successfully applied to the PRISM. + CONFIRMED_AND_REJECTED = 4; // The operation has been processed by PRISM, but rejected because of some error. +} + diff --git a/protosLib/src/main/proto/connector_api.proto b/protosLib/src/main/proto/connector_api.proto new file mode 100644 index 000000000..6521eb35a --- /dev/null +++ b/protosLib/src/main/proto/connector_api.proto @@ -0,0 +1,443 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +import "common_models.proto"; +import "connector_models.proto"; +import "node_models.proto"; + +package io.iohk.atala.prism.protos; + +/** + * The Connector API. + * An intermediate service for communication of parties: + Issuer with Holder, Holder with Verifier, etc. +*/ +service ConnectorService { + /** + * PUBLIC + * + * Checks if the service is healthy. + * Status code 0 with empty response represents a healthy and reachable service, + * while all other status codes represent issues with the service. + */ + rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse) {} + + /** + * PUBLIC + * + * Registers as a participant. + * A party registered as a participant is considered authenticated and has access + * to RPC methods with corresponding AUTHENTICATED access level. + * This is commonly expected for a user willing to register their public DID. + * The method invokes the Atala node to publish the DID to the blockchain + * or binds existing already published DID to an institution if passed. + @exclude TODO: Delete method, we should not register the DID but receive the registered one. + * Errors: + * - Invalid DID (INVALID_ARGUMENT). + * - Invalid DID document (INVALID_ARGUMENT). + * - DID Document does not match DID (INVALID_ARGUMENT). + * - DID already exists (INVALID_ARGUMENT). + * - Expected published DID (INVALID_ARGUMENT). + * - The passed DID was not found on the Atala node (INVALID_ARGUMENT). + * - Expected existing DID or Atala operation (INVALID_ARGUMENT). + */ + rpc RegisterDID (RegisterDIDRequest) returns (RegisterDIDResponse) {} + + /** + * AUTHENTICATED + * + * Generates connection tokens that can be used to instantiate connections. + * One of the participants (so called creator) is expected to generate a token and + * share with the other one (so called acceptor) via trusted and secured communication channel (e.g, via a QR-code). + * After that the acceptor instantiates a connection using the token. + */ + rpc GenerateConnectionToken (GenerateConnectionTokenRequest) returns (GenerateConnectionTokenResponse) {} + + /** + * PUBLIC + * + * Returns info about a connection token (creator info, for example). + * This is commonly used to verify whether you want to accept the connection or not. + * Errors: + * - No such connection token (UNKNOWN) + */ + rpc GetConnectionTokenInfo (GetConnectionTokenInfoRequest) returns (GetConnectionTokenInfoResponse) {} + + /** + * PUBLIC + * + * Instantiates a connection from a connection token, connection status set to accepted. + * Before the connection instantiation, a caller (acceptor) is registered as a participant. + * Creator's name, logo and DID are in the response. + * Errors: + * - A caller's DID is already used for another connection (ALREADY_EXISTS), in other words already registered + * - Passed public key is already used for another connection (ALREADY_EXISTS), in other words already registered + * - No such connection token (UNKNOWN) + */ + rpc AddConnectionFromToken (AddConnectionFromTokenRequest) returns (AddConnectionFromTokenResponse) {} + + /** + * AUTHENTICATED + * + * Retrieves a connection for a given connection token if any. + */ + rpc GetConnectionByToken (GetConnectionByTokenRequest) returns (GetConnectionByTokenResponse) {} + + /** + * AUTHENTICATED + * + * Retrieves a connection for a given connection id if any. + */ + rpc GetConnectionById (GetConnectionByIdRequest) returns (GetConnectionByIdResponse) {} + + /** + * AUTHENTICATED + * + * Gets a chunk of active connections created after the given connection, ordered by instantiation time. + * The size of the chunk doesn't exceed the passed limit. + * Both created and accepted connections will be returned. + * Errors: + * - Negative or zero limit (INVALID_ARGUMENT) + */ + rpc GetConnectionsPaginated (GetConnectionsPaginatedRequest) returns (GetConnectionsPaginatedResponse) {} + + /** + * AUTHENTICATED + * + * Revokes an active connection (this can be done from any of the sides involved). + * Once the connection is revoked: + * - No messages will be accepted. + * - The existing messages are deleted. + * - The related contact connection status gets updated. + * Errors: + * - A caller is neither sides of connection (UNKNOWN) + */ + rpc RevokeConnection (RevokeConnectionRequest) returns (RevokeConnectionResponse) {} + + /** + * AUTHENTICATED + * + * Gets a chunk of incoming messages received after the given message id, + * sorted in ascending order by reception time. + * The size of the chunk doesn't exceed the passed limit. + * Errors: + * - Negative or zero limit (INVALID_ARGUMENT) + */ + rpc GetMessagesPaginated (GetMessagesPaginatedRequest) returns (GetMessagesPaginatedResponse) {} + + /** + * AUTHENTICATED + * + * Streams all incoming messages across all the connections, received after the given optional message. + */ + rpc GetMessageStream (GetMessageStreamRequest) returns (stream GetMessageStreamResponse) {} + + /** + * AUTHENTICATED + * + * Return messages received on the given connection. + * No pagination is required, as the number of messages is small. + */ + rpc GetMessagesForConnection (GetMessagesForConnectionRequest) returns (GetMessagesForConnectionResponse) {} + + /** + * AUTHENTICATED + * + * Returns public keys that can be used for secure communication with the other end of the connection. + */ + rpc GetConnectionCommunicationKeys (GetConnectionCommunicationKeysRequest) returns (GetConnectionCommunicationKeysResponse) {} + + /** + * AUTHENTICATED + * + * Sends message over a connection. + * Errors: + * - Provided message id already exists (ALREADY_EXISTS) + * - Appropriate connection not found (NOT_FOUND) + * - Connection revoked (FAILED_PRECONDITION). + */ + rpc SendMessage (SendMessageRequest) returns (SendMessageResponse) {} + + /** + * AUTHENTICATED + * + * Sends multiple messages over many connections atomically. + * If one message cannot be sent (because of an unknown connection, for example), + * the rest also remain unsent. This method uses connection tokens instead of connections IDs. + * Errors: + * - Provided message id already exists (ALREADY_EXISTS) + * - Provided messages ids are not unique (ALREADY_EXISTS) + * - One of the connections not found by a connection token (NOT_FOUND) + * - Connection revoked (FAILED_PRECONDITION). + */ + rpc SendMessages (SendMessagesRequest) returns (SendMessagesResponse) {} + + /** + * AUTHENTICATED + * + * Returns the details for the authenticated user. + * Errors: + * - Participant not found (UNKNOWN) + */ + rpc GetCurrentUser (GetCurrentUserRequest) returns (GetCurrentUserResponse); + + /** + * AUTHENTICATED + * + * Updates an existing participant's profile. + */ + rpc UpdateParticipantProfile (UpdateProfileRequest) returns (UpdateProfileResponse) {} + + /** + * PUBLIC + * + * Returns information about the Connector and Node builds. + */ + rpc GetBuildInfo (GetBuildInfoRequest) returns (GetBuildInfoResponse); +} + +service ContactConnectionService { + /** + * WHITELISTED_DID + * + * Gets connection statuses by connection tokens. + */ + rpc GetConnectionStatus (ConnectionsStatusRequest) returns (ConnectionsStatusResponse) {} +} + +// Finds a connection by the given token. +message GetConnectionByTokenRequest { + string token = 1; // The token related to the connection. This must not be empty. +} +// The response while finding a connection by token. +message GetConnectionByTokenResponse { + io.iohk.atala.prism.protos.Connection connection = 1; +} + +// Finds a connection by the given id. +message GetConnectionByIdRequest { + string id = 1; // The id related to the connection. This must not be empty. +} +// The response while finding a connection by id. +message GetConnectionByIdResponse { + io.iohk.atala.prism.protos.ConnectionInfo connection = 1; +} + +// Requests connections instantiated by/with us, possibly after a known connection. +// +// The results are sorted in ascending orer by the time the connection was created. +message GetConnectionsPaginatedRequest { + string last_seen_connection_id = 1; // Returned connections will have been created after the last seen connection (optional field). + int32 limit = 2; // The maximum number of connections to return; must be greater than 0. +} + +// Result with instantiated connections. +message GetConnectionsPaginatedResponse { + repeated io.iohk.atala.prism.protos.ConnectionInfo connections = 1; // Connections sorted in ascending order by instantiation time. +} + +// Request to obtain information of connection token. +message GetConnectionTokenInfoRequest { + string token = 1; // The token value to get information for. +} + +// Result with information on connection token. +message GetConnectionTokenInfoResponse { + string creator_name = 2; // Creator name. + bytes creator_logo = 3; // Creator logo. + string creator_did = 4; // Creator did. + reserved 1; // Removed creator field + reserved "creator"; +} + +// Request to instantiate a connection using a token. +message AddConnectionFromTokenRequest { + // This used to allow the holder public key as (x, y). It was replaced by the holderEncodedPublicKey field. + reserved 2; + reserved "holderPublicKey"; + + // This was used to allow taking payments while creating connections, which is no longer required. + reserved 3; + reserved "paymentNonce"; + + string token = 1; // A token to instantiate a connection. + io.iohk.atala.prism.protos.EncodedPublicKey holder_encoded_public_key = 4; // Uncompressed encoded public key. +} + +// Confirmation of connection instantiation. +message AddConnectionFromTokenResponse { + io.iohk.atala.prism.protos.ConnectionInfo connection = 1; // Instantiated connection information. +} + +// Request to revoke a connection. +message RevokeConnectionRequest { + string connection_id = 1; // The ID of connection to delete. +} + +// Confirmation of connection revocation. +message RevokeConnectionResponse { +} + +// Request to generate a connection token. +message GenerateConnectionTokenRequest { + int32 count = 1; // Amount of tokens to generate (optional, the default value is 1). +} + +// Result with generated token. +message GenerateConnectionTokenResponse { + repeated string tokens = 1; // Generated tokens. +} + +// Request to return messages for us after the given known message, if any. +// Sorted by reception time in ascending order. +message GetMessagesPaginatedRequest { + string last_seen_message_id = 1; // Returned messages will have been received after the given message, if any. + int32 limit = 2; // The maximum number of messages to return. It must be greater than 0. +} + +// Response with messages. +message GetMessagesPaginatedResponse { + repeated io.iohk.atala.prism.protos.ReceivedMessage messages = 1; // Messages sorted by reception time in ascending order. +} + +// Request to stream new messages, which starts the stream from messages received after the given lastSeenMessageId +message GetMessageStreamRequest { + // Last message seen by the client, so only newer messages are returned. + string last_seen_message_id = 1; +} + +// Response for the new messages stream. +message GetMessageStreamResponse { + io.iohk.atala.prism.protos.ReceivedMessage message = 1; // The received message. +} + +// Finds available messages from the given connection. +// @exclude TODO: Remove unnecessary method, it was used before to parse received credentials but this is not required anymore. +message GetMessagesForConnectionRequest { + string connection_id = 1; +} +message GetMessagesForConnectionResponse { + repeated io.iohk.atala.prism.protos.ReceivedMessage messages = 1; +} + +// Finds the available keys to send end-to-end encrypted messages. +message GetConnectionCommunicationKeysRequest { + string connection_id = 1; // The connection we are interested in sending a message to. +} + +message GetConnectionCommunicationKeysResponse { + // Keys that can be used for communication with the other end of connection with their IDs. + // keyId inside might be empty if there is just one key in the collection. + repeated io.iohk.atala.prism.protos.ConnectionKey keys = 1; +} + +// Request to send message. +message SendMessageRequest { + string connection_id = 1; // Connection ID. + bytes message = 2; // Raw message. + // Optional id of a message. Must be valid UUID if provided. Random id will be generated + // if not provided. Error will be returned when message with the same id already exists. + string id = 3; +} + +// Confirmation of message sending. +message SendMessageResponse { + string id = 1; // Id of a message. Either provided by the sender or generated by Connector. +} + +// Request to send multiple messages. +message SendMessagesRequest { + // Messages to send. It can be empty, in which case no messages will be sent. + repeated MessageToSendByConnectionToken messages_by_connection_token = 1; +} + +// Confirmation of messages sending. +message SendMessagesResponse { + repeated string ids = 1; // Ids of a messages. Either provided by the sender or generated by Connector. +} + +// @exclude REGISTRATION AND ACCOUNT MANAGEMENT + +// Request to register DID. +// @exclude TODO: Use the method to not register the DID on the blockchain. +message RegisterDIDRequest { + oneof register_with { + // The necessary operation to publish the DID to the blockchain. + io.iohk.atala.prism.protos.SignedAtalaOperation create_did_operation = 1; + // The already published DID. + string existing_did = 5; + } + // The user's role. + // @exclude TODO: Remove, we don't use roles anymore. + Role role = 2; + + // The way to identify the institution. + string name = 3; + + // The logo linked to the institution. + bytes logo = 4; + + enum Role { + issuer = 0; + verifier = 1; + } +} + +// Request to get the authenticated user details. +message GetCurrentUserRequest {} + +// The authenticated user details. +message GetCurrentUserResponse { + Role role = 1; + string name = 2; + bytes logo = 3; + + enum Role { + issuer = 0; + verifier = 1; + } +} + +// Confirmation of DID registration. +message RegisterDIDResponse { + reserved 2; // Removed "transaction_info" field + reserved "transaction_info"; + + string did = 1; + bytes operation_id = 3; // The internal identifier of the corresponding createDID operation. Empty if used existing DID in the corresponding request. +} + +// Request to get information about this service. +message GetBuildInfoRequest {} + +// The actual service's information. +message GetBuildInfoResponse { + reserved 4; // buildTime + + string version = 1; // The service version. + string scala_version = 2; // The Scala version used by the service. + string sbt_version = 3; // The SBT version used to compile the service. + string node_version = 5; // The node service version. +} + +message ConnectionsStatusRequest { + repeated string connection_tokens = 1; +} + +message ConnectionsStatusResponse { + repeated ContactConnection connections = 1; +} + +// Request to update the participant profile name and logo +message UpdateProfileRequest { + // The way to identify the institution. + string name = 1; + // The logo linked to the institution (optional field). + // If logo is missing, this will be set to 'Empty'. + bytes logo = 2; +} + +// Confirmation of participants profile updated. +message UpdateProfileResponse {} diff --git a/protosLib/src/main/proto/connector_models.proto b/protosLib/src/main/proto/connector_models.proto new file mode 100644 index 000000000..c14e9b849 --- /dev/null +++ b/protosLib/src/main/proto/connector_models.proto @@ -0,0 +1,90 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +import "console_models.proto"; +import "credential_models.proto"; +import "google/protobuf/timestamp.proto"; + +package io.iohk.atala.prism.protos; + +// @exclude GENERAL + +// Just an elliptic curve (EC) public key represented with big integers as strings. +// +// @exclude TODO: merge with the node PublicKey +message ConnectorPublicKey { + string x = 1; + string y = 2; +} +// Public key ECPoint (uncompressed form). +message EncodedPublicKey { + bytes public_key = 1; // The bytes representing the ECPoint encoded without compression. +} + + +// @exclude CONNECTIONS + +// A connection between two parties authorizing the use of the connector as a messaging channel. +message Connection { + // The connection token used to initialize the connection with the wallet. + string connection_token = 1; + + // The connector-generated connection ID. + string connection_id = 2; +} + +// Information about the connection; both sides see the same connectionId and creation time, but each sees different participant info. +message ConnectionInfo { + reserved 2; // Removed created_deprecated field + reserved "created_deprecated"; + reserved 3; // Removed participantInfo field + reserved "participantInfo"; + + string connection_id = 1; // The connection identifier. + string token = 4; // The token used to generate the connection. + string participant_name = 5; // Participant's name. + bytes participant_logo = 6; // Participant's logo. + string participant_did = 7; // Participant's DID. + google.protobuf.Timestamp created = 8; // Timestamp of instantiation. +} + +// Communication key for connection participant. +// +// @exclude TODO: Remove this when unpublished DIDs are integrated on the apps. +message ConnectionKey { + // Key identifier; it can be empty if the participant uses only one key. + string key_id = 1; + + // The actual public key. + EncodedPublicKey key = 2; +} + + +// @exclude MESSAGES + +// Message received via a connection. +message ReceivedMessage { + reserved 2; // Removed received_deprecated field + reserved "received_deprecated"; + + string id = 1; // The unique ID for this message. + string connection_id = 3; // Connection where the message has been received. + bytes message = 4; // Raw message, which needs to be parsed to get something meaningful. AtalaMessage is the common choice. + google.protobuf.Timestamp received = 5; // The timestamp when the connector received the message. +} + +message ContactConnection { + string connection_id = 1; + string connection_token = 2; + ContactConnectionStatus connection_status = 3; +} + +message MessageToSendByConnectionToken { + string connection_token = 1; // The connection token used to accept the connection. + AtalaMessage message = 2; // Raw message. + // Optional id of a message. Must be valid UUID if provided. Random id will be generated + // if not provided. Error will be returned when message with the same id already exists. + string id = 3; +} diff --git a/protosLib/src/main/proto/console_api.proto b/protosLib/src/main/proto/console_api.proto new file mode 100644 index 000000000..6a3285a28 --- /dev/null +++ b/protosLib/src/main/proto/console_api.proto @@ -0,0 +1,1481 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +package io.iohk.atala.prism.protos; + +import "console_models.proto"; +import "common_models.proto"; +import "node_models.proto"; +import "connector_api.proto"; +import "google/protobuf/timestamp.proto"; + +/** + * The Management Console API. + * Provides a way to create and maintain issuers. +*/ +service ConsoleService { + /** + * PUBLIC + * + * Checks if the service is healthy. + * Status code 0 with empty response represents a healthy and reachable service, + * while all other status codes represent issues with the service. + */ + rpc HealthCheck (HealthCheckRequest) returns (HealthCheckResponse) {} + + /** + * AUTHENTICATED + * + * Retrieves numbers about the operations done in the Management Console for a specific time interval. + * See GetStatisticsResponse documentation on which metrics are supported. + */ + rpc GetStatistics (GetStatisticsRequest) returns (GetStatisticsResponse) {} + + /** + * PUBLIC + * + * Registers a new DID that represents an issuer. This is required to sign further requests by the issuer. + * + * Errors: + * - DID already exists (INVALID_ARGUMENT). + */ + rpc RegisterDID (RegisterConsoleDIDRequest) returns (RegisterConsoleDIDResponse) {} + + /** + * AUTHENTICATED + * + * Returns the name and the logo for the authenticated user. + * + * Errors: + * - Unknown identifier (UNKNOWN). + */ + rpc GetCurrentUser (GetConsoleCurrentUserRequest) returns (GetConsoleCurrentUserResponse) {} + + /** + * AUTHENTICATED + * + * Updates an existing participant's profile (profile is represented by name and logo). + * + * Errors: + * - Unknown identifier (UNKNOWN). + */ + rpc UpdateParticipantProfile (ConsoleUpdateProfileRequest) returns (ConsoleUpdateProfileResponse) {} + +} + +/** + * The Contacts API. + * Provides a way to add, update, and delete contacts for an authenticated issuer. + */ +service ContactsService { + /** + * AUTHENTICATED + * + * Creates a new contact for the authenticated issuer. + * Returns the created contact. + * + * Errors: + * - Generation of connection tokens failed (INVALID_ARGUMENT). + * - A group with a passed name does not exist (INVALID_ARGUMENT). + */ + rpc CreateContact (CreateContactRequest) returns (CreateContactResponse) {} + + /** + * AUTHENTICATED + * + * Creates multiple contacts atomically for the authenticated issuer, + * and binds every contact to the provided groups. + * Returns the amount of created contacts. + * + * Errors: + * - Generation of connection tokens failed (INVALID_ARGUMENT). + * - A group with a passed name does not exist (INVALID_ARGUMENT). + */ + rpc CreateContacts (CreateContactsRequest) returns (CreateContactsResponse) {} + + /** + * AUTHENTICATED + * + * Retrieves available contacts for the authenticated issuer. Several + * filter and sorting options are available for finding specific contacts. + * Returns contacts and their details in a paginated way. + * + * Errors: + * - Unexpected DB error (INTERNAL). + */ + rpc GetContacts (GetContactsRequest) returns (GetContactsResponse) {} + + /** + * AUTHENTICATED + * + * Retrieves contact's info by its identifier. + * + * Errors: + * - Unexpected DB error (INTERNAL). + */ + rpc GetContact (GetContactRequest) returns (GetContactResponse) {} + + /** + * AUTHENTICATED + * + * Updates a contact by the given identifier. + * + * Errors: + * - Unexpected DB error (INTERNAL). + */ + rpc UpdateContact (UpdateContactRequest) returns (UpdateContactResponse) {} + + /** + * AUTHENTICATED + * + * Deletes a contact from the authenticated issuer. + * + * Errors: + * - The requested contact was not deleted (INTERNAL). + * - Contact doesn not belong to issuer (INVALID_ARGUMENT). + * - Contact has some existing credentials (INVALID_ARGUMENT). + */ + rpc DeleteContact (DeleteContactRequest) returns (DeleteContactResponse) {} + + /** + * AUTHENTICATED + * DEPRECATED + * + * Generates a connection token for the given contact. + * It's an obsolete since CreateContact generates a new connection by itself. + */ + rpc GenerateConnectionTokenForContact (GenerateConnectionTokenForContactRequest) returns (GenerateConnectionTokenForContactResponse) {} +} + +/** + * The Credentials Issuance API. + * Provides a way to store credentials in the console database for further publishing. + */ +service CredentialIssuanceService { + /** + * AUTHENTICATED + * + * Creates a new credential issuance. + * Accepts a list of contacts and credential data for every contact + * (all credentials in the request are based on the same template). + * Additionally, every contact info contains a list of groups it was taken from (possibly empty). + * + * Errors: + * - Credential data validation failed (INVALID_ARGUMENT). + * - External Ids were not found (INVALID_ARGUMENT). + * - Contact Ids were not found (INVALID_ARGUMENT). + * - Missing contact id and external id (INVALID_ARGUMENT). + * - Invalid groups (INVALID_ARGUMENT). + */ + rpc CreateCredentialIssuance (CreateCredentialIssuanceRequest) returns (CreateCredentialIssuanceResponse) {} + + /** + * AUTHENTICATED + * + * The same as CreateCredentialIssuance, but takes JSON instead of data structures. + * See CreateCredentialIssuance for more details. + * + * Errors: + * - Credential data validation failed (INVALID_ARGUMENT). + * - External Ids were not found (INVALID_ARGUMENT). + * - Contact Ids were not found (INVALID_ARGUMENT). + * - Missing contact id and external id (INVALID_ARGUMENT). + * - Invalid groups (INVALID_ARGUMENT). + */ + rpc CreateGenericCredentialBulk (CreateGenericCredentialBulkRequest) returns (CreateGenericCredentialBulkResponse) {} + + /** + * AUTHENTICATED + * + * Gets a credential issuance by its identifier. + * + * Errors: + * - Unexpected DB error (INTERNAL). + */ + rpc GetCredentialIssuance (GetCredentialIssuanceRequest) returns (GetCredentialIssuanceResponse) {} +} + +/** + * The Credentials API. + * Provides a way to operate on credentials (share, delete, revoke, get detailed information from the database). + */ +service CredentialsService { + // @exclude TODO: Consider renaming this to CreateDraftCredential given that this is not published. + // @exclude TODO: Consider freezing the credential details once it gets published. + /** + * AUTHENTICATED + * + * Creates a draft credential from the authenticated issuer. + * The created credential is not published on the chain yet. + * Responses with the details of the created credential. + * See CManagerGenericCredential for more information. + * + * Errors: + * - Credential data validation failed (INVALID_ARGUMENT). + * - External Ids were not found (INVALID_ARGUMENT). + * - Contact Ids were not found (INVALID_ARGUMENT). + * - Both contact id and external id are missing, one is required (INVALID_ARGUMENT). + */ + rpc CreateGenericCredential (CreateGenericCredentialRequest) returns (CreateGenericCredentialResponse) {} + + /** + * AUTHENTICATED + * + * Retrieves the credentials created by the authenticated issuer. Several + * filter and sorting options are available for finding specific credentials. + * See CManagerGenericCredential for more information. + * + * Errors: + * - Unexpected DB error (INTERNAL). + */ + rpc GetGenericCredentials (GetGenericCredentialsRequest) returns (GetGenericCredentialsResponse) {} + + /** + * AUTHENTICATED + * + * Retrieves the credentials for the given contact created by the authenticated issuer. + * See CManagerGenericCredential for the details. + * + * Errors: + * - Unexpected DB error (INTERNAL). + */ + rpc GetContactCredentials (GetContactCredentialsRequest) returns (GetContactCredentialsResponse) {} + + /** + * AUTHENTICATED + * + * Marks a credential as shared. + * NOTE: This does not send the actual credential to the related contact, but it's supposed to be + * invoked every time that credential is sent. + * + * Errors: + * - Cannot mark the credential as shared (INTERNAL). + */ + rpc ShareCredential (ShareCredentialRequest) returns (ShareCredentialResponse) {} + + /** + * AUTHENTICATED + * + * Sends many credentials and marks them as shared. + * NOTE: This does not send the actual credential to the related contact, but it supposed to be + * invoked every time that credential is sent. + * + * Errors: + * - Cannot mark credentials as shared (INTERNAL). + */ + rpc ShareCredentials (ShareCredentialsRequest) returns (ShareCredentialsResponse) {} + + /** + * AUTHENTICATED + * DEPRECATED + * + * Retrieves node information associated with a credential. + * This method will be obsolete when we migrate to the Management Console. + */ + rpc GetBlockchainData (GetBlockchainDataRequest) returns (GetBlockchainDataResponse) {} + + /** + * AUTHENTICATED + * + * Retrieves node information associated with a batch, and optionally, specific + * credentials within a batch. + * This call invokes two other calls from node service: getBatchState and getCredentialRevocationTime. + * See Ledger for more information. + */ + rpc GetLedgerData (GetLedgerDataRequest) returns (GetLedgerDataResponse) {} + + /** + * AUTHENTICATED + * + * Publishes a credential batch to the ledger. + * This method also stores the published batch on the database. + * However, it does not store the individual credentials on the + * console (see StorePublishedCredential). + * Ensures to send IssueCredentialBatch Operation wrapped in Atala Operation. + * See Ledger and IssueCredentialBatch for more information. + * + * Errors: + * - Failed to extract content hash and issuer DID (INTERNAL). + */ + rpc PublishBatch (PublishBatchRequest) returns (PublishBatchResponse) {} + + /** + * AUTHENTICATED + * + * This request stores the information associated with a credential in the console database. + * The endpoint assumes that the credential has been published in a batch through the PublishBatch endpoint. + * + * Errors: + * - Credential with ID does not exists (INTERNAL). + * - The credential was not issued by the specified issuer (INTERNAL). + */ + rpc StorePublishedCredential (StorePublishedCredentialRequest) returns (StorePublishedCredentialResponse) {} + + /** + * AUTHENTICATED + * + * Revokes a single credential by publishing the operation on the node and storing + * the involved transaction ID in the database. + * Ensures to send the CredentialRevoked wrapped in an AtalaMessage to the contact to notify that the credential + * was revoked. + * See RevokeCredentialsOperation for more information. + * + * Errors: + * - Internal server error (INTERNAL). + */ + rpc RevokePublishedCredential (RevokePublishedCredentialRequest) returns (RevokePublishedCredentialResponse) {} + + /** + * AUTHENTICATED + * + * Deletes credentials from the Management Console database. + * Returns error when trying to delete published credentials. Revoked credentials can be deleted. + * If deletion of one credential fails, the deletion of other credentials also fails. + * + * Errors: + * - Published credentials are not revoked (INVALID_ARGUMENT). + */ + rpc DeleteCredentials (DeleteCredentialsRequest) returns (DeleteCredentialsResponse) {} +} + +/** + * The Credential Types API. + * Provides a way to operate on credential types. + */ +service CredentialTypesService { + /** + * AUTHENTICATED + * + * Retrieves the available credential types on the authenticated issuer. + * See CredentialType for more information. + */ + rpc GetCredentialTypes (GetCredentialTypesRequest) returns (GetCredentialTypesResponse) {} + + /** + * AUTHENTICATED + * + * Retrieves the credential type by its identification on the authenticated issuer. + * See CredentialTypeWithRequiredFields for more information. + */ + rpc GetCredentialType (GetCredentialTypeRequest) returns (GetCredentialTypeResponse) {} + + /** + * AUTHENTICATED + * + * Creates a new credential type on the authenticated issuer. + * Responses with the created type information. + * See CreateCredentialTypeField and CredentialTypeWithRequiredFields for more information. + * + * Errors: + * - Credential Type Incorrect Mustache Template (INVALID_ARGUMENT). + */ + rpc CreateCredentialType (CreateCredentialTypeRequest) returns (CreateCredentialTypeResponse) {} + + /** + * AUTHENTICATED + * + * Updates an existing credential type. + * + * Errors: + * - Credential Type Update Incorrect State (INVALID_ARGUMENT). + * - Credential Type Incorrect Mustache Template (INVALID_ARGUMENT). + */ + rpc UpdateCredentialType (UpdateCredentialTypeRequest) returns (UpdateCredentialTypeResponse) {} + + /** + * AUTHENTICATED + * + * Requests to change credential type state to ready on the authenticated issuer. + * + * Errors: + * - Credential Type Mark Archived As Ready (INVALID_ARGUMENT). + */ + rpc MarkAsReadyCredentialType (MarkAsReadyCredentialTypeRequest) returns (MarkAsReadyCredentialTypeResponse) {} + + /** + * AUTHENTICATED + * + * Requests to change credential type state to archived on the authenticated issuer. + */ + rpc MarkAsArchivedCredentialType (MarkAsArchivedCredentialTypeRequest) returns (MarkAsArchivedCredentialTypeResponse) {} +} + +/** + * The credential type categories API + * Provides a way to operate on credential type categories + */ +service CredentialTypeCategoriesService { + /** + * AUTHENTICATED + * + * Retrieves the available credentialTypeCategories on the authenticated issuer. + */ + rpc GetCredentialTypeCategories (GetCredentialTypeCategoriesRequest) returns (GetCredentialTypeCategoriesResponse) {} + + /** + * AUTHENTICATED + * + * Creates credential type category for authenticated issuer. + */ + rpc CreateCredentialTypeCategory (CreateCredentialTypeCategoryRequest) returns (CreateCredentialTypeCategoryResponse) {} + + /** + * AUTHENTICATED + * + * Marks credential type category for authenticated issuer. + */ + rpc ArchiveCredentialTypeCategory (ArchiveCredentialTypeCategoryRequest) returns (ArchiveCredentialTypeCategoryResponse) {} + + /** + * AUTHENTICATED + * + * Unarchives credential type category for authenticated issuer. + */ + rpc UnArchiveCredentialTypeCategory (UnArchiveCredentialTypeCategoryRequest) returns (UnArchiveCredentialTypeCategoryResponse) {} +} +/** + * The Groups API. + * Provides a way to operate on groups. + */ +service GroupsService { + /** + * AUTHENTICATED + * + * Creates a group on the authenticated issuer. + */ + rpc CreateGroup (CreateGroupRequest) returns (CreateGroupResponse) {} + + /** + * AUTHENTICATED + * + * Retrieves the available groups on the authenticated issuer. Several + * filter and sorting options are available for finding specific groups. + */ + rpc GetGroups (GetGroupsRequest) returns (GetGroupsResponse) {} + + /** + * AUTHENTICATED + * + * Updates an existing group by adding new contacts and removing some of the old ones. + * + * Errors: + * - Group does not exist (INVALID_ARGUMENT). + * - Group does not match to the issuer (INVALID_ARGUMENT). + * - Contacts do not match to the issuer (INVALID_ARGUMENT). + * - Group name is not free (INVALID_ARGUMENT). + */ + rpc UpdateGroup (UpdateGroupRequest) returns (UpdateGroupResponse) {} + + /** + * AUTHENTICATED + * + * Copies group using the existing group ID and passed name. + * Responses with a new group ID. + * + * Errors: + * - Group does not exist (INVALID_ARGUMENT). + * - Group does not match to the issuer (INVALID_ARGUMENT). + * - Group name is not free (INVALID_ARGUMENT). + */ + rpc CopyGroup (CopyGroupRequest) returns (CopyGroupResponse) {} + + /** + * AUTHENTICATED + * + * Deletes an existing group by its ID. + * + * Errors: + * - Group does not exist (INVALID_ARGUMENT). + * - Group does not match to the issuer (INVALID_ARGUMENT). + */ + rpc DeleteGroup (DeleteGroupRequest) returns (DeleteGroupResponse) {} +} + +/** + * The API for received credentials. + */ +service CredentialsStoreService { + /** + * AUTHENTICATED + * + * Stores a received credential. + * This is invoked from the wallet after receiving a credential. + */ + rpc StoreCredential (StoreCredentialRequest) returns (StoreCredentialResponse) {} + + /** + * AUTHENTICATED + * + * Finds the received credentials when filters are provided. + */ + rpc GetStoredCredentialsFor (GetStoredCredentialsForRequest) returns (GetStoredCredentialsForResponse) {} + + /** + * AUTHENTICATED + * + * Finds the latest credentialExternalId received. + * This is invoked from the wallet to know what the latest received credential is, which enables us to avoid + * processing the same received credential twice. + */ + rpc GetLatestCredentialExternalId (GetLatestCredentialExternalIdRequest) returns (GetLatestCredentialExternalIdResponse) {} +} + +/** + * Request to get usage statistics for the authenticated issuer. + * See ConsoleService.GetStatistics call for more information. + */ +message GetStatisticsRequest { + /** + * The query interval for inspection. + * Optional. If missing, the response will contain all available statistics. + */ + TimeInterval interval = 1; +} + +/** + * Response with the usage statistics for the authenticated issuer. + * See ConsoleService.GetStatistics for more information. + */ +message GetStatisticsResponse { + int32 number_of_contacts = 1; // The total number of contacts created. + int32 number_of_contacts_pending_connection = 2; // The total number of contacts that are yet to accept a connection. + int32 number_of_contacts_connected = 3; // The total number of contacts that have accepted a connection. + int32 number_of_groups = 4; // The total number of groups created. + int32 number_of_credentials_in_draft = 5; // The total number of credentials that are yet to be published on the blockchain. + int32 number_of_credentials_published = 6; // The total number of credentials published on the blockchain. + int32 number_of_credentials_received = 7; // The total number of credentials received from contacts. +} + +// @exclude TODO: Verify DID's ownership. +/** + * Request to register a DID. + * See ConsoleService.RegisterDID for more information. + */ +message RegisterConsoleDIDRequest { + string did = 1; // The DID associated with the issuer. + string name = 2; // The name of the issuer. Where applicable, it should be recognizable externally (e.g. full name of the university). + bytes logo = 3; // Optional. The logo linked to the issuer. +} + +/** + * Confirmation of DID registration. + */ +message RegisterConsoleDIDResponse {} + +/** + * Request to get the authenticated user details. + * See ConsoleService.GetCurrentUser for more information. + */ +message GetConsoleCurrentUserRequest {} + +/** + * The authenticated user details. + * See ConsoleService.GetCurrentUser for more information. + */ +message GetConsoleCurrentUserResponse { + string name = 1; // The name of the authenticated issuer. + bytes logo = 2; // Optional. The associated logo. +} + +/** + * Request to create a contact on the authenticated issuer. + */ +message CreateContactRequest { + // @exclude TODO: We likely need a list of groups instead, also, use group id instead of the name. + /** + * Optional. When present, the given contact gets assigned to a group with the given name. + */ + string group_name = 1; + + /** + * Arbitrary data for the contact. This data should be a valid JSON. If missing, "{}" will be used. + */ + string json_data = 2; + + /** + * The ID provided by the issuer when the contact was created. + * An issuer cannot have two contacts with the same external ID. + * The same ID can be used by different issuers. + */ + string external_id = 3; + + /** + * The contact's name. + */ + string name = 4; + + /** + * Metadata used to authenticate GenerateConnectionTokenRequest to connector. + * Frontend must sign GenerateConnectionTokenRequest with count value equal to number of contacts and + * pass signed request metadata through this message. + * All fields of this message are required. + */ + ConnectorRequestMetadata generate_connection_tokens_request_metadata = 5; +} + +/** + * Response after creating a contact. + */ +message CreateContactResponse { + Contact contact = 1; // The created contact. +} + +/** + * Request to create contacts on the authenticated issuer. + * The request is rejected when one or more of these conditions are met: + * - No contacts provided. + * - Any contact is invalid. + * - Contacts with duplicate external IDs. + * - Duplicate groups. + * - A group does not exist in the authenticated issuer. + */ +message CreateContactsRequest { + /** + * Optional, when present, the contacts get assigned to these groups (identified by id). + */ + repeated string groups = 1; + /** + * The contacts to create. + */ + repeated Contact contacts = 2; + message Contact { + /** + * The ID provided by the issuer when the contact was created. + * An issuer cannot have two contacts with the same external ID. + * The ID could be repeated in different issuer. + */ + string external_id = 3; + /** + * The contact's name. + */ + string name = 4; + /** + * Arbitrary data for the contact, should be a valid json, when missing, "{}" will be used, + */ + string json_data = 5; + } + /** + * Metadata used to authenticate GenerateConnectionTokenRequest to connector. + * Frontend must sign GenerateConnectionTokenRequest with count value equal to 1 and + * pass signed request metadata through this message. + * All fields of this message are required. + */ + ConnectorRequestMetadata generate_connection_tokens_request_metadata = 6; +} + +/** + * Response after creating contacts. + */ +message CreateContactsResponse { + int32 contacts_created = 1; // the number of contacts created. +} + +/** + * Request to retrieve the contacts from the authenticated issuer. + * By default, the result is sorted by the contact's creation date in ascending order. + * Contacts with the same creation date are sorted by contact ID. + */ +message GetContactsRequest { + /** + * The maximum amount of contacts to return. The amount must be greater than zero. + */ + int32 limit = 1; + /** + * Retrieves the next items based on the given scroll ID, when provided. + */ + string scroll_id = 4; + /** + * When provided, it filters the results based on the given criteria, just for the Management Console. + */ + FilterBy filter_by = 5; + /** + * When provided, it sorts the results by the given criteria. + */ + SortBy sort_by = 6; + /** + * Possible ways to filter the results from GetContactsRequest. + */ + message FilterBy { + string group_name = 1; // If provided, it only gets the contacts that belong to this group. + Date created_at = 2; // If provided, the contacts should have been created in the given date. + string name_or_external_id = 3; // If provided, the contacts should partially match the given name or externalId. The resulting SQL query will have the following clause "contacts.name ILIKE %name_or_external_id% OR contacts.external_id ILIKE %name_or_external_id%". + ContactConnectionStatus connection_status = 5; // If provided, it only gets the contacts that have this connection status. + } + /** + * The possible ways to sort the results. + */ + message SortBy { + /** + * The field used to sort the results by. + */ + Field field = 1; + /** + * Specifies the order (ascending/descending) of the results (ascending by default). + */ + SortByDirection direction = 2; + /** + * The possible fields to sort the results by. + */ + enum Field { + UNKNOWN = 0; // If the value is missing, we take the default one, CREATED_AT + CREATED_AT = 1; // The createdAt field. + NAME = 2; // The name field. + EXTERNAL_ID = 3; // The externalId field. + } + } +} + +/** + * Response with the retrieved contacts. + */ +message GetContactsResponse { + /** + * The scroll ID to retrieve the next items. + */ + string scroll_id = 2; + /** + * The contacts found filled with the credential counters. + */ + repeated ContactDetails data = 3; + /** + * Represents a contact in the response. + */ + message ContactDetails { + Contact contact = 1; // The contact. + int32 number_of_credentials_received = 2; // The number of credentials received from this contact. + int32 number_of_credentials_created = 3; // The number of credentials created for this contact (includes draft and published credentials). + } +} + +/** + * Request to retrieve a contact from the authenticated issuer. + */ +message GetContactRequest { + string contact_id = 1; // The ID used to find the contact. +} + +/** + * Response for the retrieved contact. + */ +message GetContactResponse { + Contact contact = 1; // The retrieved contact. + repeated Group groups = 2; // Available groups. + repeated StoredSignedCredential received_credentials = 3; // Credentials received. + repeated CManagerGenericCredential issued_credentials = 4; // Credentials found. +} + +/** + * Request to update a contact from the authenticated issuer. + * All fields are required. This is what the contact will be updated to. + */ +message UpdateContactRequest { + string contact_id = 1; // The ID for the contact to update. + string new_external_id = 2; // The new externalId. + string new_name = 3; // The new name. + string new_json_data = 4; // The new arbitrary JSON data. If missing, "{}" will be used +} + +/** + * Response after updating the contact. + */ +message UpdateContactResponse {} + +/** + * Request to delete a contact from the authenticated issuer. + */ +message DeleteContactRequest { + /** + * The ID used to delete the contact. + */ + string contact_id = 1; + /** + * If true, related credentials will be deleted along with the contact. + * If false and has any related credentials, the request will fail to delete the contact. + * If false and has no related credentials, only the contact will be deleted. + */ + bool delete_credentials = 2; +} + +/** + * Response for the deleted contact. + */ +message DeleteContactResponse {} + +/** + * Request to generate a connection token for the given contact on the authenticated issuer. + */ +message GenerateConnectionTokenForContactRequest { + string contact_id = 1; // The contact that will be linked to the token. +} + +/** + * Response after generating a connection token. + */ +message GenerateConnectionTokenForContactResponse { + string token = 1; // The token that needs to be shared with the user to accept the connection. +} + +/** + * Request to create a new credential issuance. + * It creates all needed contacts, groups, and credentials. After that it binds credentials to the contacts. + */ +message CreateCredentialIssuanceRequest { + string name = 1; // Name of the credential issuance. + string credential_type_id = 2; // The ID (UUID) of the credential type used as template for this credential. + repeated CredentialIssuanceContact credential_issuance_contacts = 3; // The contacts and their credential data. +} + +/** + * Response to creating a credential issuance. + */ +message CreateCredentialIssuanceResponse { + string credential_issuance_id = 1; // ID of the credential issuance just created. +} + +/** + * Request to create a credential issuance for the authenticated issuer. + * The difference with CreateCredentialIssuanceRequest is that this request takes a JSON parameter. + */ +message CreateGenericCredentialBulkRequest { + /** + * The JSON that contains the credentials data in this issuance. + * The expected structure is: + *
{
+   *    "issuance_name": String,
+   *    "credential_type_id": String,
+   *    "drafts" : [
+   *      {
+   *        "external_id": String,
+   *        "credential_data": JSON,
+   *        "group_ids": [String],
+   *      }
+   *    ]
+   * }
+ */ + string credentials_json = 1; +} + +/** + * Response when a bulk of credentials is created. + */ +message CreateGenericCredentialBulkResponse { + string credential_issuance_id = 1; // The ID of the credential issuance. +} + +/** + * Request to get a credential issuance. + */ +message GetCredentialIssuanceRequest { + string credential_issuance_id = 1; // ID of the credential issuance. +} + +/** + * Response to getting a credential issuance. + */ +message GetCredentialIssuanceResponse { + string name = 1; // Name of the credential issuance. + string credential_type_id = 2; // // The ID (UUID) of the credential type used as template for this credential. + google.protobuf.Timestamp created_at = 3; // Timestamp when the credential issuance was created. + repeated CredentialIssuanceContact credential_issuance_contacts = 4; // The contacts and their credential data. +} + +/** + * Request to get a list of all credential types on the authenticated issuer. + */ +message GetCredentialTypesRequest {} + +/** + * Response with the retrieved credential types. + */ +message GetCredentialTypesResponse { + repeated CredentialType credential_types = 1; // List of the credential types. +} + +/** + * Request to get a credential type on the authenticated issuer. + */ +message GetCredentialTypeRequest { + string credential_type_id = 1; // Id of the credential type. +} + +/** + * Response with the retrieved credential type. + */ +message GetCredentialTypeResponse { + CredentialTypeWithRequiredFields credential_type = 1; // The retrieved credential type. +} + +/** + * Request to create a credential type on the authenticated issuer. + */ +message CreateCredentialTypeRequest { + CreateCredentialType credential_type = 2; // New credential type. +} + +/** + * Response with the created credential type. + */ +message CreateCredentialTypeResponse { + CredentialTypeWithRequiredFields credential_type = 1; // The created credential type. +} + +/** + * Request to update a credential type on the authenticated issuer. + */ +message UpdateCredentialTypeRequest { + UpdateCredentialType credential_type = 2; // Credential type to update. +} + +/** + * Empty response after credential type update. + */ +message UpdateCredentialTypeResponse {} + +/** + * Request to change credential type state to ready on the authenticated issuer. + */ +message MarkAsReadyCredentialTypeRequest { + string credential_type_id = 1; // Credential type to update. +} + +/** + * Empty response after state update. + */ +message MarkAsReadyCredentialTypeResponse {} + +/** + * Request to change state to archived in credential type on the authenticated issuer. + */ +message MarkAsArchivedCredentialTypeRequest { + string credential_type_id = 1; // Credential type to update. +} + +/** + * Empty response after state update. + */ +message MarkAsArchivedCredentialTypeResponse {} + + +/** + * Request to get a list of all credential type categories on the authenticated issuer. + */ +message GetCredentialTypeCategoriesRequest {} + +/** + * Response with the retrieved credential type categories. + */ +message GetCredentialTypeCategoriesResponse { + repeated CredentialTypeCategory credential_type_categories = 1; +} + +/** + * Request to create a credential type category + */ +message CreateCredentialTypeCategoryRequest { + CreateCredentialTypeCategory credential_type_category = 1; +} + +/** + * Response with the created credential type + */ +message CreateCredentialTypeCategoryResponse { + CredentialTypeCategory credential_type_category = 1; +} + +/** + * Request to archive a credential type category by id + */ +message ArchiveCredentialTypeCategoryRequest { + string credential_type_category_id = 1; +} + +/** + * Response with archived credential type category + */ +message ArchiveCredentialTypeCategoryResponse { + CredentialTypeCategory credential_type_category = 1; +} + +/** + * Request to unarchive a credential type category by id + */ +message UnArchiveCredentialTypeCategoryRequest { + string credential_type_category_id = 1; +} + +/** + * Response with unCredentialTypeCategoryarchived credential type category + */ +message UnArchiveCredentialTypeCategoryResponse { + CredentialTypeCategory credential_type_category = 1; +} + + +/** + * Request to create a group on the authenticated issuer. + * See GroupsService.CreateGroup for more information. + */ +message CreateGroupRequest { + string name = 1; // The group name, which must not exist. + repeated string contact_ids = 2; // Contacts to put in the new group. New contacts cannot be duplicate. +} + +/** + * Response after creating a group. + */ +message CreateGroupResponse { + Group group = 1; // The group created and its associated details. +} + +/** + * Request to retrieve the available groups on the authenticated issuer. + * See GroupsService.GetGroups for more information. + */ +message GetGroupsRequest { + /** + * Optional, default value is 10. The maximum amount of groups to return. + */ + int32 limit = 2; + /** + * Optional, default is 0. The offset for pagination. + */ + int32 offset = 3; + /** + * When provided, filter the results based on the given criteria, just for the Management Console. + */ + FilterBy filter_by = 4; + /** + * Optional. When provided, it sorts the results by the given criteria (sorted by name in ascending order by default). + */ + SortBy sort_by = 5; + /** + * The possible ways to filter the results from GetGroupsRequest. + */ + message FilterBy { + string name = 1; // If provided, it returns the groups containing the given name (case insensitive). + Date created_after = 2; // If provided, it returns groups created at the given date or after. + Date created_before = 3; // If provided, it returns groups created before or at the given date. + string contact_id = 4; // If provided, it returns groups related to the given contact only. + } + /** + * The possible ways to sort the results. + */ + message SortBy { + Field field = 1; // The field used to sort the results by. + SortByDirection direction = 2; // Sorts results in ascending/descending order (ascending by default). + + /** + * The possible fields to sort the results by. + */ + enum Field { + UNKNOWN = 0; // If the value is missing, we take the default one: NAME. + NAME = 1; // The name field. + CREATED_AT = 2; // The createdAt field. + NUMBER_OF_CONTACTS = 3; // Number of contacts. + } + } +} + +/** + * Response with the available groups. + */ +message GetGroupsResponse { + /** + * The available groups. + */ + repeated Group groups = 1; + /** + * The total number of groups that matches the filterBy criteria supplied in request, + * used to offset based pagination to compute the number of available pages. + */ + int32 total_number_of_groups = 2; +} + +/** + * Request to update a group. + * See GroupsService.UpdateGroupRequest for more information. + */ +message UpdateGroupRequest { + string group_id = 1; // The ID of the existing group. + repeated string contact_ids_to_add = 2; // The list of contact IDs to be added to the specified group. + repeated string contact_ids_to_remove = 3; // The list of contact IDs to be removed from the specified group. + string name = 4; // The new name for the group. +} + +/** + * Response after updating a group. + * See GroupsService.UpdateGroup to see possible errors. + */ +message UpdateGroupResponse {} + +/** + * Request to copy a group. + */ +message CopyGroupRequest { + string group_id = 1; // The ID of the existing group. + string name = 2; // The new name of the copied group. +} + +/** + * Response after copying a group. + * See GroupsService.CopyGroup to see possible errors. + */ +message CopyGroupResponse { + string group_id = 1; // The new group's ID. +} + +/** + * Request to delete a group. + */ +message DeleteGroupRequest { + string group_id = 1; // The ID of the existing group to delete. +} + +/** + * Response after deleting a group. + * See GroupsService.DeleteGroup to see possible errors. + */ +message DeleteGroupResponse {} + +/** + * Request to create a credential on the authenticated issuer. + * See CredentialsService.CreateGenericCredential for more information. + */ +message CreateGenericCredentialRequest { + /** + * The contact ID to link the credential to. + * Required if the external ID is not provided, it is ignored otherwise. + */ + string contact_id = 1; + /** + * The credential payload as a JSON string. + * A valid non-empty JSON is required. + */ + string credential_data = 2; + /** + * The ID provided by the issuer when the contact was created. If this timestamp is not provided, + * the contact ID is expected. + */ + string external_id = 4; + /** + * The ID (UUID) of the credential type used as a template for this credential. + */ + string credential_type_id = 5; +} + +/** + * Response when a credential is created. + * See CManagerGenericCredential, CredentialsService.CreateGenericCredential for more information. + */ +message CreateGenericCredentialResponse { + CManagerGenericCredential generic_credential = 1; // The credential details. +} + +/** + * The authenticated issuer is retrieving its issued credentials. + * The results are sorted in ascending order by creation date. Results with same creation date are sorted by their ID. + * See CredentialsService.GetGenericCredentials for more information. + */ +message GetGenericCredentialsRequest { + /** + * Optional, default value is 10. The maximum amount of credentials to return. + */ + int32 limit = 1; + + /** + * Removed lastSeenCredentialId field + */ + reserved 2; + reserved "lastSeenCredentialId"; + + /** + * Optional, default is 0. The offset for pagination. + */ + int32 offset = 3; + + /** + * When provided, filter the results based on the given criteria, just for the Management Console. + */ + FilterBy filter_by = 4; + /** + * Optional. When provided, it sorts the results by the given criteria (sorted by name in ascending order by default). + */ + SortBy sort_by = 5; + + /** + * The possible ways to filter the results from GetGenericCredentialsRequest. + */ + message FilterBy { + string credential_type = 1; // If provided, it returns the credentials containing the given type. + Date created_after = 2; // If provided, it returns credentials created at the given date or after. + Date created_before = 3; // If provided, it returns credentials created before or at the given date. + CredentialStatus credentialStatus = 4; // If provided credentials being in the status are returned + ContactConnectionStatus contactConnectionStatus = 5; // If provided credentials belonging to a contact with the status are returned + string contactExternalId = 6; // If provided credentials belonging to a contact with the external id are returned + string contactName = 7; // If provided credentials belonging to contact with a name containing the specified substring + } + + /** + * The possible ways to sort the results. + */ + message SortBy { + Field field = 1; // The field used to sort the results by. + SortByDirection direction = 2; // Sorts results in ascending/descending order (ascending by default). + + /** + * The possible fields to sort the results by. + */ + enum Field { + UNKNOWN = 0; // If the value is missing, we take the default one: NAME. + CREDENTIAL_TYPE = 1; // The credential type field. + CREATED_ON = 2; // The createdOn field. + EXTERNAL_ID = 3; // The external_id field. + CREDENTIAL_STATUS = 4; // The credential status. https://github.com/input-output-hk/atala-prism-management-console-web/blob/e23cfa606036ac718660730ac5dd38cd0028bf02/src/APIs/helpers/credentialHelpers.js#L22 + } + } +} + +/** + * Response with the credentials found. + */ +message GetGenericCredentialsResponse { + repeated CManagerGenericCredential credentials = 1; // The retrieved credentials. + int32 totalCount = 2; // Total number of credentials retrievable ignoring pagination. +} + +// @exclude TODO: Consider renaming this to MarkCredentialAsSent. +/** + * Request to share a credential, which just marks the credential as sent. + * This is intended to be invoked after sending the credential through the connector. + */ +message ShareCredentialRequest { + string cmanager_credential_id = 2; // cmanager internal credential ID. +} + +/** + * Response after sharing a credential. + */ +message ShareCredentialResponse {} + +/** + * Request to share many credentials, which sends credentials through the connector and marks them as sent. + * See CredentialsService.ShareCredentials for more information. + */ +message ShareCredentialsRequest { + /** + * Non-empty list of IDs of credentials that will be sent to the connector, and later marked as shared. + */ + repeated string credentials_ids = 1; + /** + * Request to connector containing messages with signed credentials. + */ + SendMessagesRequest send_messages_request = 2; + /** + * Metadata used to authenticate SendMessagesRequest to connector. + * Frontend must sign SendMessagesRequest that can be fetched. + * From GetShareCredentialsRequestToSign gRPC Management Console method and + * pass signed request through this message. + * All fields of this message are required. + */ + ConnectorRequestMetadata send_messages_request_metadata = 3; +} + +/** + * Response after sharing a credential. + */ +message ShareCredentialsResponse {} + +/** + * Request to get the credentials for the given contact. + * As the expected amount of credentials per contact is small, no pagination is required. + */ +message GetContactCredentialsRequest { + string contact_id = 1; // The contact identifier. +} + +/** + * Response with the contact credentials. + * See CManagerGenericCredential for more information. + */ +message GetContactCredentialsResponse { + repeated CManagerGenericCredential generic_credentials = 1; // The credentials found. + int32 totalCount = 2; // Total number of credentials found. +} + +/** + * Request to get blockchain-related information for a credential. + */ +message GetBlockchainDataRequest { + string encoded_signed_credential = 1; // Encoded credential we want to retrieve information for. +} + +/** + * Response with the information found in the blockchain. + * See TransactionInfo for more information. + */ +message GetBlockchainDataResponse { + TransactionInfo issuance_proof = 1; // Transaction information associated with the credential issuance event. +} + +/** + * Request to store a received credential. + * See CredentialsStoreService.StoreCredential for more information. + */ +message StoreCredentialRequest { + string connection_token = 1; // The connection token related to the connector message that carried the credential. + string encoded_signed_credential = 2; // The encoded signed data. + string credential_external_id = 3; // A credential's external id (currently, the ID of the connector message that carried it). + string batch_inclusion_proof = 4; // Inclusion proof associated to the encodedSignedCredential. +} + +/** + * Response after storing a received credential. + */ +message StoreCredentialResponse {} + +/** + * Request to find the received credentials. + */ +message GetStoredCredentialsForRequest { + // @exclude TODO: Rename to `contactId` after removing legacy methods. + string individual_id = 1; // Optional, allows to retrieve received credentials from a single contact. +} + +/** + * Response with the received credentials. + * See StoredSignedCredential for more information. + */ +message GetStoredCredentialsForResponse { + repeated StoredSignedCredential credentials = 1; // The received credentials. + int32 totalCount = 2; // Total number of received credentials. +} + +/** + * Request to find the latest credentialExternalId. + */ +message GetLatestCredentialExternalIdRequest {} + +/** + * Response with the latest credentialExternalId. + */ +message GetLatestCredentialExternalIdResponse { + string latest_credential_external_id = 1; // The identifier of the latest received credential. +} + +/** + * Request to publish a credential batch to the blockchain. + * See CredentialsService.PublishBatch, IssueCredentialBatch, SignedAtalaOperation for more information. + */ +message PublishBatchRequest { + SignedAtalaOperation issue_credential_batch_operation = 1; // A signed instance of IssueCredentialBatch operation. +} + +/** + * Response after publishing a batch. + * See CredentialsService.PublishBatch, PublishBatchRequest, TransactionInfo for more information. + */ +message PublishBatchResponse { + reserved 2; // Removed "transaction_info" field. + reserved "transaction_info"; + + string batch_id = 1; // The protocol assigned ID for the batch. + bytes operation_id = 3; // The internal identifier of the corresponding operation. +} + +/** + * Request to store a credential for which its batch has been published. + * See CredentialsService.StorePublishedCredential for more information. + */ +message StorePublishedCredentialRequest { + string encoded_signed_credential = 1; // The encoded credential to store. + string console_credential_id = 2; // Management Console internal credential ID. + string batch_id = 3; // The protocol ID associated with the batch that contains this credential. + string encoded_inclusion_proof = 4; // The Merkle proof of inclusion for the batch associated with the credential. +} + +/** + * Response after publishing a credential. + */ +message StorePublishedCredentialResponse {} + +/** + * Request to revoke a published credential. + * See CredentialsService.RevokePublishedCredential, RevokeCredentials, SignedAtalaOperation for more information. + */ +message RevokePublishedCredentialRequest { + /** + * The internal credential ID, used to link the revocation transaction ID. It must be an UUID. + */ + string credential_id = 1; + /** + * A signed instance of the RevokeCredentials operation. + * Note that even though the operation allows many credentials to be revoked, the request + * is only accepted when only a single credential involved. + */ + SignedAtalaOperation revoke_credentials_operation = 2; +} + +/** + * Response after revoking a credential. + * See CredentialsService.RevokePublishedCredential, TransactionInfo for more information. + */ +message RevokePublishedCredentialResponse { + reserved 1; // Removed "transaction_info" field. + reserved "transaction_info"; + + bytes operation_id = 2; // The internal identifier of the corresponding operation. +} + +/** + * Request to delete many credentials. + */ +message DeleteCredentialsRequest { + repeated string credentials_ids = 1; // IDs of credentials to delete (non-empty). +} + +/** + * Confirmation of credential deletion. + */ +message DeleteCredentialsResponse {} + +/** + * Requests ledger data for a specific batch and credential recorded by the node. + */ +message GetLedgerDataRequest { + /** + * The batchId (assigned by the protocol) that we want information to be returned for. + */ + string batch_id = 1; + /** + * Optional. The credential hash that we want information to be returned for. We assume that the credential + * was issued in the batch associated with `batchId`. + */ + bytes credential_hash = 2; +} + +/** + * Returns the ledger data from the node associated to a batch and credential. + * See CredentialsService.GetLedgerData and LedgerData for more information. + */ +message GetLedgerDataResponse { + LedgerData batch_issuance = 1; // If present, the ledger data associated with the issuance of the batch requested. + LedgerData batch_revocation = 2; // If present, the ledger data associated with the revocation of the batch requested. + LedgerData credential_revocation = 3; // If present, the ledger data associated with the revocation of the credential requested. +} + +/** + * Request to update participant's profile name and logo. + * See ConsoleService.UpdateParticipantProfile for more information. + */ +message ConsoleUpdateProfileRequest { + string name = 1; // The name of the issuer. Where applicable, it should be recognizable externally (e.g. full name of the university). + bytes logo = 2; // Optional. The logo linked to the issuer. If logo is missing, the field will be set to empty. +} + +/** + * Confirmation of participant's profile updated. + * See ConsoleService.UpdateParticipantProfile for more information. + */ +message ConsoleUpdateProfileResponse {} diff --git a/protosLib/src/main/proto/console_models.proto b/protosLib/src/main/proto/console_models.proto new file mode 100644 index 000000000..78923e2ad --- /dev/null +++ b/protosLib/src/main/proto/console_models.proto @@ -0,0 +1,244 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +package io.iohk.atala.prism.protos; + +import "common_models.proto"; +import "google/protobuf/timestamp.proto"; + +/** + * Indicates the status of the contact's connection. + */ +enum ContactConnectionStatus { + STATUS_MISSING = 0; // Default value, represents the lack of status. + // @exclude TODO remove after removing console functionality from connector + STATUS_INVITATION_MISSING = 1; // No connection token is generated yet, kept for compatibility with connector as the console backend generates the tokens while creating contacts. + STATUS_CONNECTION_MISSING = 2; // The contact has been invited and the connection token has been generated. + STATUS_CONNECTION_ACCEPTED = 3; // The contact accepted the connection. + STATUS_CONNECTION_REVOKED = 4; // The contact rejected the connection. +} + +/** + * Indicates the state of credential. + */ +enum CredentialStatus { + CREDENTIAL_STATUS_MISSING = 0; // Default value, represents the lack of status. + CREDENTIAL_DRAFT = 1; + CREDENTIAL_SIGNED = 2; + CREDENTIAL_SENT = 3; + CREDENTIAL_REVOKED = 4; +} + +/** + * Represents a contact. + */ +message Contact { + reserved 7; // Reserved createdAt_deprecated field + reserved "createdAt_deprecated"; + + string contact_id = 1; // The internal ID to identify the contact. + string external_id = 2; // The ID provided by the issuer when the contact was created. It is commonly used to match the issuer's record keeping system, for example, it could be the student ID for a university. + string json_data = 3; // Arbitrary data for the contact. Should be a valid JSON. If missing, "{}" will be used. + ContactConnectionStatus connection_status = 4; // The connection status for this contact. + string connection_token = 5; // The connection token used to get this contact connected, present when the status is ConnectionMissing. + string connection_id = 6; // The necessary connection ID to send messages to this contact, present when the status is ConnectionAccepted. + string name = 8; // The contact's name, only used by the Management Console. + google.protobuf.Timestamp created_at = 9; // The timestamp when the contact was created. +} + +/** + * Contains credential data and a list of groups for a contact. + */ +message CredentialIssuanceContact { + string contact_id = 1; // ID of the contact the credential data is about. + string credential_data = 2; // Actual credential data of the contact, in JSON format. + repeated string group_ids = 3; // IDs of the groups the contact was taken from, empty if added directly. +} + +/** + * Indicates the state of the credential type. + */ +enum CredentialTypeState { + CREDENTIAL_TYPE_UNKNOWN = 0; // Invalid value, should not happen. + CREDENTIAL_TYPE_DRAFT = 1; // The credential type is still being defined and is not final, it cannot be used to create a new credential. + CREDENTIAL_TYPE_READY = 2; // The credential type is ready to use, it can be used to create a new credential. + CREDENTIAL_TYPE_ARCHIVED = 3; // The credential type is archived, it cannot be used to create a new credential. +} + +/** + * Indicates the state of the credential type category. + */ +enum CredentialTypeCategoryState { + CREDENTIAL_TYPE_CATEGORY_DRAFT = 0; // The credential type category is still being defined and is not final, it cannot be used to create a new credential. + CREDENTIAL_TYPE_CATEGORY_READY = 1; // The credential type category is ready to use, it can be used to create a new credential. + CREDENTIAL_TYPE_CATEGORY_ARCHIVED = 2; // The credential type category is archived, it cannot be used to create a new credential. +} + +/** + * Indicates the data type of a field in the credential. + */ +enum CredentialTypeFieldType { + CREDENTIAL_TYPE_FIELD_UNKNOWN = 0; // Invalid value, should not happen. + CREDENTIAL_TYPE_FIELD_STRING = 1; // Any string. + CREDENTIAL_TYPE_FIELD_INT = 2; // Positive and negative integer numbers. + CREDENTIAL_TYPE_FIELD_BOOLEAN = 3; // True/False only. + CREDENTIAL_TYPE_FIELD_DATE = 4; // The date as string in DD/MM/YY or DD/MM/YYYY format. +} + +/** + * Describes the field in the credential type. + */ +message CredentialTypeField { + string id = 1; // UUID + string credential_type_id = 2; // Identifier of the credential template which uses this field. + string name = 3; // Field name. + string description = 4; // Field description. + CredentialTypeFieldType type = 5; // Type of the data for this field. +} + +/** + * Create new field for credential templates. + */ +message CreateCredentialTypeField { + string name = 1; // Field name. + string description = 2; // Field description. + CredentialTypeFieldType type = 3; // Type of the data for this field. +} + +/** + * Credential type entity. It represents the template for issuing new credentials. + */ +message CredentialType { + string id = 1; // UUID + string name = 2; // The credential type name. + CredentialTypeState state = 3; // The credential type state, can be: draft, ready, or archived. + string template = 4; // The credential type template, HTML with optional mustache syntax variables. + google.protobuf.Timestamp created_at = 5; // The timestamp when the credential type was created. + bytes icon = 6; // Optional. Icon of the credential type. +} + +/** + * Credential type entity needed to create a new record, all fields are required. + */ +message CreateCredentialType { + string name = 1; // The credential type name -required field. + string template = 2; // The credential type template, HTML with optional mustache syntax variables. + bytes icon = 3; // Optional. Icon of the credential type. + repeated CreateCredentialTypeField fields = 4; // List of the credential type fields. +} + +/** + * Credential type category entity needed to create a new record, all fields are required. + */ +message CreateCredentialTypeCategory { + string name = 1; + CredentialTypeCategoryState state = 2; +} + +/** + * Credential type category as represented in Database with all fields. + */ +message CredentialTypeCategory { + string id = 1; + string name = 2; + CredentialTypeCategoryState state = 3; + string institution_id = 4; +} + +/** + * Credential type entity needed for the update. + */ +message UpdateCredentialType { + string id = 1; // UUID (required). + string name = 2; // Optional. The credential type name. + string template = 3; // Optional. The credential type template. + bytes icon = 4; // Optional. The icon of the credential type. + repeated CreateCredentialTypeField fields = 5; // Optional. List of the credential type fields. If present, the fields will be overwritten. +} + +/** + * Credential type with required fields. + */ +message CredentialTypeWithRequiredFields { + CredentialType credential_type = 1; // Credential type. + repeated CredentialTypeField required_fields = 2; // List of the credential type fields. +} + +/** + * Represents a group that contacts can be assigned to. + * A group is generally used to collect the contacts related to the same issuance event, + * for a university, it can be a graduation group, for example. + */ +message Group { + reserved 3; // Removed createdAt_deprecated field + reserved "createdAt_deprecated"; + + string name = 1; // The group name. + string id = 2; // The unique ID for the group, generated by the server. + int32 number_of_contacts = 4; // The number of contacts associated with the group. + google.protobuf.Timestamp created_at = 5; // The time when the group was created. +} + +/** + * Represents all the details of the credential. + */ +message CManagerGenericCredential { + reserved 8; // Removed nodeCredentialId field + reserved "nodeCredentialId"; + reserved 11; // Removed publicationStoredAt_deprecated field + reserved "publicationStoredAt_deprecated"; + reserved 14; // Removed sharedAt_deprecated field + reserved "sharedAt_deprecated"; + reserved 15; // Removed issuance_proof field. + reserved "issuance_proof"; + reserved 18; // Removed revocation_proof field. + reserved "revocation_proof"; + + string credential_id = 1; // Credential identifier internal to the cmanager. + string issuer_id = 2; // Issuer identifier internal to the cmanager. + string contact_id = 3; // Contact identifier internal to cmanager. + string credential_data = 4; // The arbitrary JSON data involved in the credential (claims). + string issuer_name = 5; // The name of the issuer according to the cmanager internal data. + string contact_data = 7; // The arbitrary JSON data related to the contact. + + // @exclude The fields below will only be populated after the credential is published to the blockchain. + + bytes issuance_operation_hash = 9; // The hash of the associated issuance operation. + string encoded_signed_credential = 10; // The actual published credential. + string external_id = 12; // The ID provided by the issuer when the contact was created. + ContactConnectionStatus connection_status = 13; // Checks if a contact has accepted the connection request. + string batch_inclusion_proof = 16; // Inclusion proof that shows that encodedSignedCredential is a member of a batch. + string batch_id = 17; // The batch ID defined by protocol, representing the batch that contains the encodedSignedCredential. + google.protobuf.Timestamp publication_stored_at = 19; // The timestamp when the publication data was stored in the database. + google.protobuf.Timestamp shared_at = 20; // The last time the credential was sent to the related contact. + bytes revoked_on_operation_id = 21; // The operation where the credential was requested to be revoked (if any). + OperationStatus revoked_on_operation_status = 22; // The operation status when the credential was requested to be revoked (if any). +} + +/** + * Represents a received credential. + */ +message StoredSignedCredential { + reserved 3; // Removed storedAt_deprecated field + reserved "storedAt_deprecated"; + + // @exclude TODO: Rename to contactId. + string individual_id = 1; // The contact that sent the credential. + string encoded_signed_credential = 2; // The signed credential encoded as a string. + string external_id = 4; // The external ID associated with the contact that sent the credential. + string batch_inclusion_proof = 5; // The inclusion proof associated with the encodedSignedCredential. + google.protobuf.Timestamp stored_at = 6; // The timestamp when the credential was stored in the database. +} + +/** + * Metadata used to authenticate some request to the connector. + * All fields of this message are required. + */ +message ConnectorRequestMetadata { + string did = 1; // value of did + string did_key_id = 2; // id of did key + string did_signature = 3; // Base64-encoded signature of request and request nonce signed with the issuer's private key. + string request_nonce = 4; // Base64-encoded request nonce. +} diff --git a/protosLib/src/main/proto/credential_models.proto b/protosLib/src/main/proto/credential_models.proto new file mode 100644 index 000000000..4dda1f760 --- /dev/null +++ b/protosLib/src/main/proto/credential_models.proto @@ -0,0 +1,76 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +import "common_models.proto"; +import "status.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/any.proto"; + +package io.iohk.atala.prism.protos; + + +message ProofRequest { + repeated string type_ids = 1; + string connection_token = 2; +} + +message EncryptedMessage { + // The identifier of the key used to encrypt the message. This might be empty if the receiver uses only one key. + string key_id = 1; + // Encrypted content of the message. After decryption, it should be deserialized as an AtalaMessage instance. + bytes encrypted_content = 2; +} + +// ATA-3250: Until we implement e2e encryption, we will share +// credentials using this message. +message PlainTextCredential { + string encoded_credential = 1; // The encoded and signed credential. + string encoded_merkle_proof = 2; // The encoded Merkle proof of inclusion associated with the encodedCredential. +} + +// Used to notify the apps that a credential was revoked. +message CredentialRevoked { + string encoded_credential = 1; // The encoded and signed credential. + string reason = 2; // An optional revocation reason, as provided by the issuer. +} + +message AtalaErrorMessage { + google.rpc.Status status = 1; +} + +message CredentialOwnershipVerificationRequest { + CredentialAndVerificationNonce credential_and_verification_nonce = 1; +} + +message CredentialOwnershipVerificationResponse { + bytes signature = 1; + bytes nonce = 2; +} + +message CredentialAndVerificationNonce { + string encoded_credential = 1; + bytes nonce = 2; +} + +message AtalaMessage { + oneof message { + CredentialOwnershipVerificationRequest credential_ownership_verification_request = 1; + CredentialOwnershipVerificationResponse credential_ownership_verification_response = 2; + ProofRequest proof_request = 3; + EncryptedMessage encrypted_message = 4; + PlainTextCredential plain_credential = 6; + CredentialRevoked credential_revoked = 8; + AtalaErrorMessage atala_error_message = 9; + google.protobuf.Any custom_message = 10; // variant to use for messages from external components, e.g. Mirror + } + reserved 5; //removed variant MirrorMessage mirror_message = 5; + reserved "mirror_message"; + reserved 7; // removed variant KycBridgeMessage kyc_bridge_message = 7; + reserved "kyc_bridge_message"; + + // Optional, if set, it's the id of an existing message from the same connection. + // It means that sent message is a reply to one of messages received by the sender. + string reply_to = 101; +} diff --git a/protosLib/src/main/proto/cviews_api.proto b/protosLib/src/main/proto/cviews_api.proto new file mode 100644 index 000000000..fcc221061 --- /dev/null +++ b/protosLib/src/main/proto/cviews_api.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +package io.iohk.atala.prism.protos; + +import "cviews_models.proto"; + +// The API for the credential views. +service CredentialViewsService { + // Gets the available view templates. + rpc GetCredentialViewTemplates (GetCredentialViewTemplatesRequest) returns (GetCredentialViewTemplatesResponse) {} +} + +// Request to get the available view templates. +message GetCredentialViewTemplatesRequest {} +// Response with the available view templates. +message GetCredentialViewTemplatesResponse { + repeated CredentialViewTemplate templates = 1; // the available templates +} diff --git a/protosLib/src/main/proto/cviews_models.proto b/protosLib/src/main/proto/cviews_models.proto new file mode 100644 index 000000000..7af8503e1 --- /dev/null +++ b/protosLib/src/main/proto/cviews_models.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +package io.iohk.atala.prism.protos; + +// Represents a credential template. +message CredentialViewTemplate { + int64 id = 1; // The unique ID for this template. + string name = 2; // The template's name. + string encoded_logo_image = 3; // Logo image encoded in base64 as a UTF-8 string. + string logo_image_mime_type = 4; // The MIME Type for the logo. + + // HTML view with replaceable variables enclosed by double brackets, e.g., "{{foo.bar}}" + string html_template = 5; +} diff --git a/protosLib/src/main/proto/health.proto b/protosLib/src/main/proto/health.proto new file mode 100644 index 000000000..53e6e0325 --- /dev/null +++ b/protosLib/src/main/proto/health.proto @@ -0,0 +1,63 @@ +// Copyright 2015 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The canonical version of this proto can be found at +// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto + +syntax = "proto3"; + +package grpc.health.v1; + +option csharp_namespace = "Grpc.Health.V1"; +option go_package = "google.golang.org/grpc/health/grpc_health_v1"; +//option java_multiple_files = true; +//option java_outer_classname = "HealthProto"; +//option java_package = "io.grpc.health.v1"; + +message HealthCheckRequest { + string service = 1; +} + +message HealthCheckResponse { + enum ServingStatus { + UNKNOWN = 0; + SERVING = 1; + NOT_SERVING = 2; + SERVICE_UNKNOWN = 3; // Used only by the Watch method. + } + ServingStatus status = 1; +} + +service Health { + // If the requested service is unknown, the call will fail with status + // NOT_FOUND. + rpc Check(HealthCheckRequest) returns (HealthCheckResponse); + + // Performs a watch for the serving status of the requested service. + // The server will immediately send back a message indicating the current + // serving status. It will then subsequently send a new message whenever + // the service's serving status changes. + // + // If the requested service is unknown when the call is received, the + // server will send a message setting the serving status to + // SERVICE_UNKNOWN but will *not* terminate the call. If at some + // future point, the serving status of the service becomes known, the + // server will send a new message with the service's serving status. + // + // If the call terminates with status UNIMPLEMENTED, then clients + // should assume this method is not supported and should not retry the + // call. If the call terminates with any other status (including OK), + // clients should retry the call with appropriate exponential backoff. + rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse); +} diff --git a/protosLib/src/main/proto/intdemo/intdemo_api.proto b/protosLib/src/main/proto/intdemo/intdemo_api.proto new file mode 100755 index 000000000..d47c248d9 --- /dev/null +++ b/protosLib/src/main/proto/intdemo/intdemo_api.proto @@ -0,0 +1,57 @@ +syntax = "proto3"; + +import "intdemo/intdemo_models.proto"; + +package io.iohk.atala.prism.intdemo.protos; + +// This service simulates an application run by a government body who use io.iohk.atala's connector. +service IDService { + rpc GetConnectionToken (GetConnectionTokenRequest) returns (GetConnectionTokenResponse) {} + rpc GetSubjectStatus (GetSubjectStatusRequest) returns (GetSubjectStatusResponse) {} + rpc GetSubjectStatusStream (GetSubjectStatusRequest) returns (stream GetSubjectStatusResponse) {} + rpc SetPersonalData (SetPersonalDataRequest) returns (SetPersonalDataResponse) {} +} + +// This service simulates an application run by a university who use io.iohk.atala's connector. +service DegreeService { + rpc GetConnectionToken (GetConnectionTokenRequest) returns (GetConnectionTokenResponse) {} + rpc GetSubjectStatus (GetSubjectStatusRequest) returns (GetSubjectStatusResponse) {} + rpc GetSubjectStatusStream (GetSubjectStatusRequest) returns (stream GetSubjectStatusResponse) {} +} + +// ... a company's application +service EmploymentService { + rpc GetConnectionToken (GetConnectionTokenRequest) returns (GetConnectionTokenResponse) {} + rpc GetSubjectStatus (GetSubjectStatusRequest) returns (GetSubjectStatusResponse) {} + rpc GetSubjectStatusStream (GetSubjectStatusRequest) returns (stream GetSubjectStatusResponse) {} +} + +// ... another company's application +service InsuranceService { + rpc GetConnectionToken (GetConnectionTokenRequest) returns (GetConnectionTokenResponse); + rpc GetSubjectStatus (GetSubjectStatusRequest) returns (GetSubjectStatusResponse) {} + rpc GetSubjectStatusStream (GetSubjectStatusRequest) returns (stream GetSubjectStatusResponse) {} +} + +message GetSubjectStatusRequest { + string connection_token = 1; +} + +message GetSubjectStatusResponse { + SubjectStatus subject_status = 1; +} + +message GetConnectionTokenRequest { +} + +message GetConnectionTokenResponse { + string connection_token = 1; +} + +message SetPersonalDataRequest { + string connection_token = 1; + string first_name = 2; + Date date_of_birth = 3; +} + +message SetPersonalDataResponse {} diff --git a/protosLib/src/main/proto/intdemo/intdemo_models.proto b/protosLib/src/main/proto/intdemo/intdemo_models.proto new file mode 100644 index 000000000..5901372fa --- /dev/null +++ b/protosLib/src/main/proto/intdemo/intdemo_models.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package io.iohk.atala.prism.intdemo.protos; + +message Date { + int32 year = 1; // positive value + int32 month = 2; // value in the [1, 12] interval + int32 day = 3; // value in the [1, 31] interval (depending on the month, the max value might be 28 +} + +enum SubjectStatus { + UNCONNECTED = 0; + CONNECTED = 1; + CREDENTIAL_AVAILABLE = 2; + CREDENTIAL_SENT = 3; + CREDENTIAL_RECEIVED = 4; +} diff --git a/protosLib/src/main/proto/node_api.proto b/protosLib/src/main/proto/node_api.proto new file mode 100644 index 000000000..69a1d9c69 --- /dev/null +++ b/protosLib/src/main/proto/node_api.proto @@ -0,0 +1,376 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +package io.iohk.atala.prism.protos; + +import "common_models.proto"; +import "node_models.proto"; + +import "google/protobuf/timestamp.proto"; + +/** + * Service for PRISM Node API. Provides a way to store, retrieve and update + * Decentralized identifiers (DIDs), and Credentials' commitments into/from the underlying blockchain. + */ +service NodeService { + /** + * PUBLIC + * + * Sends a request that can be used to check service health. + * All PRISM services expose an RPC that accepts this message as request. + */ + rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse) {} + + /** + * PUBLIC + * + * Retrieves a DID Document associated to a DID. + * + * Errors: + * - Invalid long form DID (INVALID_ARGUMENT) + * - DID format not supported (INVALID_ARGUMENT) + * - Invalid DID (INVALID_ARGUMENT) + * - Unknown DID (INVALID_ARGUMENT) + */ + rpc GetDidDocument(GetDidDocumentRequest) returns (GetDidDocumentResponse) {} + + /** + * PUBLIC + * + * Retrieves the Node version info. + */ + rpc GetNodeBuildInfo(GetNodeBuildInfoRequest) returns (GetNodeBuildInfoResponse) {} + + /** + * PUBLIC + * + * Retrieves the Node version info. + */ + rpc GetNodeNetworkProtocolInfo(GetNodeNetworkProtocolInfoRequest) returns (GetNodeNetworkProtocolInfoResponse) {} + + /** + * PUBLIC + * + * Finds the state for a given credential's batch. + * + * Errors: + * - Invalid batch id (INVALID_ARGUMENT) + * - Unknown batch id (INVALID_ARGUMENT) + */ + rpc GetBatchState(GetBatchStateRequest) returns (GetBatchStateResponse) {} + + /** + * PUBLIC + * + * Finds the time when a credential was revoked. + * + * Errors: + * - Invalid batch id (INVALID_ARGUMENT) + * - Unknown batch id (INVALID_ARGUMENT) + */ + rpc GetCredentialRevocationTime(GetCredentialRevocationTimeRequest) returns (GetCredentialRevocationTimeResponse) {} + + /** + * PUBLIC + * + * Retrieves the status of an operation. + */ + rpc GetOperationInfo(GetOperationInfoRequest) returns (GetOperationInfoResponse) {} + + /** + * PUBLIC + * + * Timestamp of the latest block processed by PRISM Node. + */ + rpc GetLastSyncedBlockTimestamp(GetLastSyncedBlockTimestampRequest) returns (GetLastSyncedBlockTimestampResponse) {} + + /** + * PUBLIC + * + * Schedules a list of operations for further publication. + */ + rpc ScheduleOperations(ScheduleOperationsRequest) returns (ScheduleOperationsResponse) {} +} + +service NodeExplorerService { + /** + * WHITELISTED_DID + * + * Return a list of scheduled but unconfirmed operations. + */ + rpc GetScheduledOperations(GetScheduledOperationsRequest) returns (GetScheduledOperationsResponse) {} + + /** + * WHITELISTED_DID + * + * Return a list of wallet transactions. + */ + rpc GetWalletTransactionsPaginated(GetWalletTransactionsRequest) returns (GetWalletTransactionsResponse) {} + + /** + * WHITELISTED_DID + * + * Return the Node Wallet Balance + */ + rpc GetWalletBalance(GetWalletBalanceRequest) returns (GetWalletBalanceResponse) {} + + /** + * WHITELISTED_DID + * + * Retrieves list of available metrics. + */ + rpc GetAvailableMetrics(GetAvailableMetricsRequest) returns (GetAvailableMetricsResponse) {} + + /** + * WHITELISTED_DID + * + * Get statistics + */ + rpc GetNodeStatistics(GetNodeStatisticsRequest) returns (GetNodeStatisticsResponse) {} +} + +/** + * Retrieve statistics from the Node. + */ +message GetNodeStatisticsRequest { + repeated string metrics = 1; +} + +/** + * Statistics from the Node. + */ +message GetNodeStatisticsResponse { + repeated double metrics = 1; +} + +/** + * Request to find metrics exposed by Node. + * See NodeService.GetAvailableMetrics for more information. + */ +message GetAvailableMetricsRequest {} + +/** + * Response with a list of metrics exposed by Node. + * See NodeService.GetAvailableMetrics for more information. + */ +message GetAvailableMetricsResponse { + repeated string metrics = 1; +} + +/** + * Request to find a DID Document. + * See NodeService.GetDidDocument for more information. + */ +message GetDidDocumentRequest { + string did = 1; // The DID. +} +/** + * Response to a DID Document query. + * See NodeService.GetDidDocument for more information. + */ +message GetDidDocumentResponse { + DIDData document = 1; // The DID Document. + google.protobuf.Timestamp last_synced_block_timestamp = 5; // Timestamp of the latest synchronized block. + bytes last_update_operation = 6; // The hash of the last did update operation. +} + +/** + * Request to get the Node version info. + * See NodeService.GetNodeBuildInfo for more information. + */ +message GetNodeBuildInfoRequest { +} +/** + * Response with the Node version info. + * See NodeService.GetNodeBuildInfo for more information. + */ +message GetNodeBuildInfoResponse { + reserved 4; + + string version = 1; // The actual version. + string scala_version = 2; // The Scala version used to compile the app. + string sbt_version = 3; // The SBT version used to compile the app. +} + +/** + * Request to get the Node version info. + * See NodeService.GetNodeBuildInfo for more information. + */ +message GetNodeNetworkProtocolInfoRequest { +} +/** + * Response with the Node Protocol version info. + * See NodeService.GetNodeProtocolVersionInfo for more information. + */ +message GetNodeNetworkProtocolInfoResponse { + ProtocolVersion supported_network_protocol_version = 5; // Network protocol version number supported by Node. + ProtocolVersion current_network_protocol_version = 6; // Current network protocol version number. +} + +/** + * Request to get the credential's batch state. + * See NodeService.GetBatchState for more information. + */ +message GetBatchStateRequest { + string batch_id = 1; // The batch ID. +} +/** + * Response with the credential's batch state. + * See NodeService.GetBatchState for more information. + */ +message GetBatchStateResponse { + /** + * DID suffix used to sign the IssueCredentialBatch operation. + */ + string issuer_did = 1; + + /** + * The Merkle root used for the IssueCredential operation. + */ + bytes merkle_root = 2; + + /** + * Underlying blockchain data that refers to the transaction that + * contains the IssueCredential operation associated with the credential. + */ + LedgerData publication_ledger_data = 3; + + /** + * Underlying blockchain data that refers to the transaction that + * contains the RevokeCredential operation associated with the credential. + * This is optional. + */ + LedgerData revocation_ledger_data = 4; + + /** + * Timestamp of the latest synchronized block. + */ + google.protobuf.Timestamp last_synced_block_timestamp = 5; + + /** + * The hash of the credential to query about. + */ + bytes issuance_hash = 6; +} + +/** + * Request to get the credential's revocation time. + * See NodeService.GetCredentialRevocationTime for more information. + */ +message GetCredentialRevocationTimeRequest { + string batch_id = 1; // The ID corresponding to the credential to query about. + bytes credential_hash = 2; // The hash of the credential to query about. +} +/** + * Response with the credential's revocation time. + * See NodeService.GetCredentialRevocationTime for more information. + */ +message GetCredentialRevocationTimeResponse { + LedgerData revocation_ledger_data = 1; // The ledger data when the credential was revoked. This is optional. + google.protobuf.Timestamp last_synced_block_timestamp = 2; // Timestamp of the latest synchronized block. +} + +/** + * Request to get the operation status. + * See NodeService.GetOperationInfo for more information. + */ +message GetOperationInfoRequest { + bytes operation_id = 1; // Operation identifier. The identifier is returned to the corresponding operation request. +} +/** + * Response with the current operation status. + * See NodeService.GetOperationInfo for more information. + */ +message GetOperationInfoResponse { + OperationStatus operation_status = 1; // Contains the status of this operation. + string transaction_id = 3; // Transaction identifier containing the operation. Presented only when operation was approved by the ledger. + google.protobuf.Timestamp last_synced_block_timestamp = 2; // Timestamp of the latest synchronized block. + string details = 4; // Contains additional information about the operation state. For example, error descriptions. Can be empty. +} + +/** + * Request to retrieve the timestamp of the latest synchronized (processed by PRISM Node) block. + * See NodeService.GetLastSyncedBlockTimestampRequest for more information. + */ +message GetLastSyncedBlockTimestampRequest { +} +/** + * Response with the timestamp of the latest synchronized (processed by PRISM Node) block. + * See NodeService.GetLastSyncedBlockTimestampResponse for more information. + */ +message GetLastSyncedBlockTimestampResponse { + /** + * Timestamp of the latest synchronized (processed by PRISM Node) block. + */ + google.protobuf.Timestamp last_synced_block_timestamp = 1; +} + +/** + * Request to retrieve transaction info and operations outputs. + */ +message ScheduleOperationsRequest { + /** + * List of signed operations to apply. The operations will be applied in the order specified here. + */ + repeated SignedAtalaOperation signed_operations = 1; // a list of signed operations +} + +/** + * Response with the transaction info and operations outputs. + */ +message ScheduleOperationsResponse { + /** + * The responses for scheduled operations, ordered the same as the operations sent in ScheduleOperationsRequest. + */ + repeated OperationOutput outputs = 1; +} + +/** + * Request to retrieve all scheduled but not confirmed Atala operations. + */ +message GetScheduledOperationsRequest { + /** + * Operations of which type should be returned. + */ + OperationType operationsType = 1; + + enum OperationType { + AnyOperationType = 0; // Any operation + CreateDidOperationOperationType = 1; + UpdateDidOperationOperationType = 2; + IssueCredentialBatchOperationType = 3; + RevokeCredentialsOperationType = 4; + ProtocolVersionUpdateOperationType = 5; + } +} + +message GetScheduledOperationsResponse { + repeated SignedAtalaOperation scheduled_operations = 1; // a list of scheduled operations +} + +/** + * Request to retrieve wallet transactions, either ongoing or confirmed. + * Pagination included. + */ +message GetWalletTransactionsRequest { + TransactionState state = 1; // Transaction state: either ongoing or confirmed + string last_seen_transaction_id = 2; // Last seen transaction id + int32 limit = 3; // The maximum number of transactions to return; must be greater than 0. + + enum TransactionState { + Ongoing = 0; // Transactions which hasn't been confirmed by Prism Node + Confirmed = 1; // Transactions which ahs been confirmed by Prism Node + } +} + +message GetWalletTransactionsResponse { + repeated TransactionInfo transactions = 1; +} + +message GetWalletBalanceRequest { +} +message GetWalletBalanceResponse { + bytes balance = 1; +} diff --git a/protosLib/src/main/proto/node_internal.proto b/protosLib/src/main/proto/node_internal.proto new file mode 100644 index 000000000..167a08fe7 --- /dev/null +++ b/protosLib/src/main/proto/node_internal.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +import "node_models.proto"; + +package io.iohk.atala.prism.protos; + +/** + * Represent a block that holds operations. + * @exclude Intended for internal usage inside. Not publicly accessible from gRPC. + */ +message AtalaBlock { + reserved 1; // Represents the version of the block. Deprecated + repeated SignedAtalaOperation operations = 2; // A signed operation, necessary to post anything on the blockchain. +} + +/** + * Wraps an AtalaBlock and its metadata. + * @exclude Intended for internal usage inside. Not publicly accessible from gRPC. + */ +message AtalaObject { + reserved 1; // Removed block_hash field. + reserved "block_hash"; + + int32 block_operation_count = 2; // Number of operations in the block. + int32 block_byte_length = 3; // Byte length of the block. + AtalaBlock block_content = 4; // The block content. +} diff --git a/protosLib/src/main/proto/node_models.proto b/protosLib/src/main/proto/node_models.proto new file mode 100644 index 000000000..816b6d527 --- /dev/null +++ b/protosLib/src/main/proto/node_models.proto @@ -0,0 +1,247 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.iohk.atala.prism.protos"; + +package io.iohk.atala.prism.protos; + +import "common_models.proto"; +import "google/protobuf/timestamp.proto"; + +// Includes timestamping details about a blockchain's block. +message TimestampInfo { + reserved 1; // Removed blockTimestamp_deprecated field + reserved "blockTimestamp_deprecated"; + + uint32 block_sequence_number = 2; // The transaction index inside the underlying block. + uint32 operation_sequence_number = 3; // The operation index inside the AtalaBlock. + google.protobuf.Timestamp block_timestamp = 4; // The timestamp provided from the underlying blockchain. +} + +// Every key has a single purpose: +enum KeyUsage { + // UNKNOWN_KEY is an invalid value - Protobuf uses 0 if no value is provided and we want the user to explicitly choose the usage. + UNKNOWN_KEY = 0; + + // This is the most privileged key-type, when any other key is lost, you could use this to recover the others. + MASTER_KEY = 1; + + // This key-type is used for issuing credentials only, it should be kept in a safe place + // to avoid malicious credentials being issued. + ISSUING_KEY = 2; + + // This key-type is used for end-to-end encrypted communication, whoever wants to send a message should + // use this key-type to encrypt the content. + COMMUNICATION_KEY = 3; + + // This key-type is used to authenticate requests or logging into services. + AUTHENTICATION_KEY = 4; + + // This key-type is used for revoking credentials only, it should be kept in a safe place + // to avoid malicious credentials being issued. + REVOCATION_KEY = 5; +} + +/** + * Holds the necessary data to recover an Elliptic Curve (EC)'s public key. + * @exclude TODO: Consider renaming this to ECPublicKeyData. + */ +message ECKeyData { + string curve = 1; // The curve name, like secp256k1. + bytes x = 2; // The x coordinate, represented as bytes. + bytes y = 3; // The y coordinate, represented as bytes. +} + +/** + * Holds the compressed representation of data needed to recover Elliptic Curve (EC)'s public key. + * @exclude TODO: Consider renaming this to CompressedECPublicKeyData. + */ +message CompressedECKeyData { + string curve = 1; // The curve name, like secp256k1. + bytes data = 2; // compressed Elliptic Curve (EC) public key data. +} + +/** + * Represents a public key with metadata, necessary for a DID document. + * @exclude TODO: Consider renaming this to something more specific, like DIDPublicKey. + */ +message PublicKey { + reserved 3, 4; + string id = 1; // The key identifier within the DID Document. + KeyUsage usage = 2; // The key's purpose. + LedgerData added_on = 5; // The ledger details related to the event that added the key to the DID Document. + LedgerData revoked_on = 6; // The ledger details related to the event that revoked the key to the DID Document. + + // The key's representation. + oneof key_data { + ECKeyData ec_key_data = 8; // The Elliptic Curve (EC) key. + CompressedECKeyData compressed_ec_key_data = 9; // Compressed Elliptic Curve (EC) key. + }; +} + +// The DID Document's data. +message DIDData { + string id = 1; // The DID suffix, where DID is in form did:prism:[DID suffix] + repeated PublicKey public_keys = 2; // The keys that belong to this DID Document. +} + +// The operation to create a public DID. +message CreateDIDOperation { + DIDCreationData did_data = 1; // DIDCreationData with public keys + + // The data necessary to create a DID. + message DIDCreationData { + reserved 1; // Removed DID id field which is empty on creation + repeated PublicKey public_keys = 2; // The keys that belong to this DID Document. + } +} + +// The necessary data to add a key to a DID. +message AddKeyAction { + PublicKey key = 1; // The key to include. +} + +// The necessary data to remove a key from a DID. +message RemoveKeyAction { + string keyId = 1; // the key id to remove +} + +// The potential details that can be updated in a DID. +message UpdateDIDAction { + + // The action to perform. + oneof action { + AddKeyAction add_key = 1; // Used to add a new key to the DID. + RemoveKeyAction remove_key = 2; // Used to remove a key from the DID. + } +} + +// Specifies the necessary data to update a public DID. +message UpdateDIDOperation { + bytes previous_operation_hash = 1; // The hash of the operation that issued the DID. + string id = 2; // @exclude TODO: To be redefined after we start using this operation. + repeated UpdateDIDAction actions = 3; // The actual updates to perform on the DID. +} + +// Represents a credential's batch. +// +// Check the protocol docs to understand it. +message CredentialBatchData { + string issuer_did = 1; // The DID suffix that issues the credential's batch. + bytes merkle_root = 2; // The Merkle root for the credential's batch. +} + +// Specifies the data to issue a credential batch. +message IssueCredentialBatchOperation { + CredentialBatchData credential_batch_data = 1; // The actual credential batch data. +} + +// Specifies the credentials to revoke (the whole batch, or just a subset of it). +message RevokeCredentialsOperation { + bytes previous_operation_hash = 1; // The hash of the operation that issued the batch. + string credential_batch_id = 2; // The corresponding batch ID, as returned in IssueCredentialBatchResponse. + repeated bytes credentials_to_revoke = 3; // The hashes of the credentials to revoke. If empty, the full batch is revoked. +} + +// Specifies the protocol version update +message ProtocolVersionUpdateOperation { + string proposer_did = 1; // The DID suffix that proposes the protocol update. + ProtocolVersionInfo version = 2; // Information of the new version +} + + +message ProtocolVersion { + // Represent the major version + int32 major_version = 1; + // Represent the minor version + int32 minor_version = 2; +} + +message ProtocolVersionInfo { + reserved 2, 3; + string version_name = 1; // (optional) name of the version + int32 effective_since = 4; // Cardano block number that tells since which block the update is enforced + + // New major and minor version to be announced, + // If major value changes, the node MUST stop issuing and reading operations, and upgrade before `effective_since` because the new protocol version. + // If minor value changes, the node can opt to not update. All events _published_ by this node would be also + // understood by other nodes with the same major version. However, there may be new events that this node won't _read_ + ProtocolVersion protocol_version = 5; +} + +message DeactivateDIDOperation { + bytes previous_operation_hash = 1; // The hash of the operation that issued the DID. + string id = 2; // DID Suffix of the DID to be deactivated +} + +// The possible operations affecting the blockchain. +message AtalaOperation { + // The actual operation. + oneof operation { + // Used to create a public DID. + CreateDIDOperation create_did = 1; + + // Used to update an existing public DID. + UpdateDIDOperation update_did = 2; + + // Used to issue a batch of credentials. + IssueCredentialBatchOperation issue_credential_batch = 3; + + // Used to revoke a credential batch. + RevokeCredentialsOperation revoke_credentials = 4; + + // Used to announce new protocol update + ProtocolVersionUpdateOperation protocol_version_update = 5; + + // Used to deactivate DID + DeactivateDIDOperation deactivate_did = 6; + }; +} + +// A signed operation, necessary to post anything on the blockchain. +message SignedAtalaOperation { + string signed_with = 1; // The key ID used to sign the operation, it must belong to the DID that signs the operation. + bytes signature = 2; // The actual signature. + AtalaOperation operation = 3; // The operation that was signed. +} + +// Ledger data associated to a protocol event. +// Note that the difference with TransactionInfo is that this message contains a full +// timestamp, and there is no expectation for it to be optional. +message LedgerData { + string transaction_id = 1; // ID of the transaction. + Ledger ledger = 2; // Ledger the transaction was published to. + TimestampInfo timestamp_info = 3; // The timestamp of the protocol event. +} + +// Used to encode the responses of the operations issued in an AtalaBlock. +message OperationOutput { + oneof result { + // Represents the response provided by IssueCredentialBatchOperation. + IssueCredentialBatchOutput batch_output = 1; + // Represents the response provided by CreateDIDOperation. + CreateDIDOutput create_did_output = 2; + // Represents the response provided by UpdateDIDOperation. + UpdateDIDOutput update_did_output = 3; + // Represents the response provided by RevokeCredentialOperation. + RevokeCredentialsOutput revoke_credentials_output = 4; + // Represents the response provided by ProtocolVersionUpdateOperation. + ProtocolVersionUpdateOutput protocol_version_update_output = 7; + DeactivateDIDOutput deactivate_did_output = 8; + } + oneof operation_maybe { + bytes operation_id = 5; // Operation identifier. + string error = 6; // Error description if PRISM Node service haven't scheduled the operation. + } +} + +message IssueCredentialBatchOutput { + string batch_id = 1; +} +message CreateDIDOutput { + string did_suffix = 1; +} +message UpdateDIDOutput {} +message RevokeCredentialsOutput {} +message ProtocolVersionUpdateOutput {} +message DeactivateDIDOutput {} diff --git a/protosLib/src/main/proto/package.json b/protosLib/src/main/proto/package.json new file mode 100644 index 000000000..36afdf83f --- /dev/null +++ b/protosLib/src/main/proto/package.json @@ -0,0 +1,10 @@ +{ + "name": "@input-output-hk/atala-prism-protos", + "version": "VERSION", + "description": "raw proto files for Atala PRISM project", + "repository": { + "type": "git", + "url": "git+https://github.com/input-output-hk/atala-prism-sdk.git" + }, + "author": "input-output-hk" +} diff --git a/protosLib/src/main/proto/resources/markdown.tmpl b/protosLib/src/main/proto/resources/markdown.tmpl new file mode 100644 index 000000000..056eb47f7 --- /dev/null +++ b/protosLib/src/main/proto/resources/markdown.tmpl @@ -0,0 +1,95 @@ +# gRPC API Reference + + +## Table of Contents +{{range .Files}} +{{$file_name := .Name}}- [{{.Name}}](#{{.Name}}) + {{- if .Messages }} + {{range .Messages}} - [{{.LongName}}](#{{.FullName}}) + {{end}} + {{- end -}} + {{- if .Enums }} + {{range .Enums}} - [{{.LongName}}](#{{.FullName}}) + {{end}} + {{- end -}} + {{- if .Extensions }} + {{range .Extensions}} - [File-level Extensions](#{{$file_name}}-extensions) + {{end}} + {{- end -}} + {{- if .Services }} + {{range .Services}} - [{{.Name}}](#{{.FullName}}) + {{end}} + {{- end -}} +{{end}} + +{{range .Files}} +{{$file_name := .Name}} + +

Top

+ +## {{.Name}} +{{.Description}} + +{{range .Messages}} + + +### {{.LongName}} +{{.Description}} + +{{if .HasFields}} +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +{{range .Fields -}} + | {{.Name}} | [{{.LongType}}](#{{.FullType}}) | {{.Label}} | {{if (index .Options "deprecated"|default false)}}**Deprecated.** {{end}}{{.Description | replace "\n" "
"}}{{if .DefaultValue}} Default: {{.DefaultValue}}{{end}} | +{{end}} +{{end}} + +{{if .HasExtensions}} +| Extension | Type | Base | Number | Description | +| --------- | ---- | ---- | ------ | ----------- | +{{range .Extensions -}} + | {{.Name}} | {{.LongType}} | {{.ContainingLongType}} | {{.Number}} | {{.Description | replace "\n" "
"}}{{if .DefaultValue}} Default: {{.DefaultValue}}{{end}} | +{{end}} +{{end}} + +{{end}} + +{{range .Enums}} + + +### {{.LongName}} +{{.Description}} + +| Name | Number | Description | +| ---- | ------ | ----------- | +{{range .Values -}} + | {{.Name}} | {{.Number}} | {{.Description | replace "\n" "
"}} | +{{end}} + +{{end}} + +{{if .HasExtensions}} + + +### File-level Extensions +| Extension | Type | Base | Number | Description | +| --------- | ---- | ---- | ------ | ----------- | +{{range .Extensions -}} + | {{.Name}} | {{.LongType}} | {{.ContainingLongType}} | {{.Number}} | {{.Description | replace "\n" "
"}}{{if .DefaultValue}} Default: `{{.DefaultValue}}`{{end}} | +{{end}} +{{end}} + +{{range .Services}} + + +### {{.Name}} +{{.Description}} + +| Method Name | Request Type | Response Type | Description | +| ----------- | ------------ | ------------- | ------------| +{{range .Methods -}} + | {{.Name}} | [{{.RequestLongType}}](#{{.RequestFullType}}){{if .RequestStreaming}} stream{{end}} | [{{.ResponseLongType}}](#{{.ResponseFullType}}){{if .ResponseStreaming}} stream{{end}} | {{.Description | replace "\n" "
"}} | +{{end}} +{{end}} + +{{end}} diff --git a/protosLib/src/main/proto/status.proto b/protosLib/src/main/proto/status.proto new file mode 100644 index 000000000..5bd51aa2f --- /dev/null +++ b/protosLib/src/main/proto/status.proto @@ -0,0 +1,47 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc; + +import "google/protobuf/any.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/rpc/status;status"; +option java_multiple_files = true; +option java_outer_classname = "StatusProto"; +option java_package = "com.google.rpc"; +option objc_class_prefix = "RPC"; + +// The `Status` type defines a logical error model that is suitable for +// different programming environments, including REST APIs and RPC APIs. It is +// used by [gRPC](https://github.com/grpc). Each `Status` message contains +// three pieces of data: error code, error message, and error details. +// +// You can find out more about this error model and how to work with it in the +// [API Design Guide](https://cloud.google.com/apis/design/errors). +message Status { + // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. + int32 code = 1; + + // A developer-facing error message, which should be in English. Any + // user-facing error message should be localized and sent in the + // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. + string message = 2; + + // A list of messages that carry the error details. There is a common set of + // message types for APIs to use. + repeated google.protobuf.Any details = 3; +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 58a851af1..5a34bfbef 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,11 +1,47 @@ pluginManagement { repositories { + gradlePluginPortal() + mavenCentral() google() + } + resolutionStrategy { + eachPlugin { + when (requested.id.id) { + "binary-compatibility-validator" -> { + useModule("org.jetbrains.kotlinx:binary-compatibility-validator:${requested.version}") + } + "com.android.application", "com.android.library" -> { + useModule("com.android.tools.build:gradle:${requested.version}") + } + } + } + } +} + +buildscript { + repositories { gradlePluginPortal() mavenCentral() + mavenLocal() + google() + maven("https://plugins.gradle.org/m2/") + // Needed for Kotlin coroutines that support new memory management mode + maven { + url = uri("https://maven.pkg.jetbrains.space/public/p/kotlinx-coroutines/maven") + } + } + + dependencies { + classpath("io.arrow-kt:arrow-ank-gradle:0.11.0") } } + rootProject.name = "wallet-sdk" +include(":protosLib") + include(":wallet-sdk") -include(":core-sdk") \ No newline at end of file +include(":core-sdk") +include(":authenticate-sdk") +include(":prism-crypto") + diff --git a/wallet-sdk/build.gradle.kts b/wallet-sdk/build.gradle.kts index 3f005f369..2ab1cacf4 100644 --- a/wallet-sdk/build.gradle.kts +++ b/wallet-sdk/build.gradle.kts @@ -3,7 +3,7 @@ import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackOutput.Target version = rootProject.version -val currentModuleName: String = "core-sdk" +val currentModuleName: String = "core_sdk" val os: OperatingSystem = OperatingSystem.current() plugins { diff --git a/wallet-sdk/src/androidMain/AndroidManifest.xml b/wallet-sdk/src/androidMain/AndroidManifest.xml new file mode 100644 index 000000000..1bef8c601 --- /dev/null +++ b/wallet-sdk/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/wallet-sdk/wallet_sdk.podspec b/wallet-sdk/wallet_sdk.podspec index 61422b876..43d0bbab5 100644 --- a/wallet-sdk/wallet_sdk.podspec +++ b/wallet-sdk/wallet_sdk.podspec @@ -6,7 +6,7 @@ Pod::Spec.new do |spec| spec.authors = 'IOG' spec.license = '' spec.summary = 'Wallet-SDK - DIDComm V2 operation' - spec.vendored_frameworks = 'build/cocoapods/framework/core-sdk.framework' + spec.vendored_frameworks = 'build/cocoapods/framework/core_sdk.framework' spec.libraries = 'c++' spec.ios.deployment_target = '13.0' spec.osx.deployment_target = '12.0' @@ -16,7 +16,7 @@ Pod::Spec.new do |spec| spec.pod_target_xcconfig = { 'KOTLIN_PROJECT_PATH' => ':wallet-sdk', - 'PRODUCT_MODULE_NAME' => 'core-sdk', + 'PRODUCT_MODULE_NAME' => 'core_sdk', } spec.script_phases = [