Skip to content

Commit

Permalink
feat: decline support in MRZ and eMRTD requests (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
genaris authored Dec 3, 2024
1 parent 96b47cb commit 6a16c6a
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 20 deletions.
44 changes: 44 additions & 0 deletions doc/service-agent-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ In addition, it supports a notification mechanism to subscribe to any event the
- [Call Accept](#call-accept)
- [Call Reject](#call-reject)
- [Call End](#call-end)
- [MRZ Data Request](#mrz-data-request)
- [MRZ Data Submit](#mrz-data-submit)
- [eMRTD Data Request](#emrtd-data-request)
- [eMRTD Data Submit](#emrtd-data-submit)
- [Identity Proof Item types](#identity-proof-item-types)
- [Verifiable Credential](#verifiable-credential)
- [Request value](#request-value)
Expand Down Expand Up @@ -513,10 +517,13 @@ Request the other party to provide the Machine Readable Zone string from a valid

Submit Machine Readable Zone data. This message may be sent either individually or as a response to a MRZ Data Request.

The state can be one of 'submitted', 'declined', 'timeout' or 'error', depending on how the flow went. The latter is used for unspecified errors (e.g. User Agent not capable of handling the request).

```json
{
...
"type": "mrz-data-submit",
"state": MrtdSubmitState,
"mrzData": MrzData
}
```
Expand All @@ -539,6 +546,43 @@ Submit Machine Readable Zone data. This message may be sent either individually

More info about the meaning of each field (and validity) can be found in [MRZ](https://github.com/cheminfo/mrz), the underlying library we are using for MRZ parsing.

#### eMRTD Data Request


Request the other party to read and provide eMRTD (Electronic Machine Readable Travel Document) data from a compatible electronic document.

```json
{
...
"type": "emrtd-data-request",
}
```

> TODO: Add parameters once supported by @2060.io/credo-ts-didcomm-mrtd module

#### eMRTD Data Submit

Submit data retrieved from an electronic Machine Readable Travel Document. This message may be sent either individually or as a response to an eMRTD Data Request.


The state can be one of 'submitted', 'declined', 'timeout' or 'error', depending on how the flow went. The latter is used for unspecified errors (e.g. User Agent not capable of handling the request).

```json
{
...
"type": "emrtd-data-submit",
"state": MrtdSubmitState,
"dataGroups": EMrtdData
}
```

`dataGroups` is a JSON object with two basic fields:

- raw: object containing all data groups read from the chip in base64 format
- parsed: object containing all interpreted fields and a global 'valid' flag to indicate if the document structure and integrity has been properly validated

> TODO: Document better the interpreted fields or refer to the libraries to check the format.

### Identity Proof Item types

When a Credential Issuance is requested, the issuer might require the recipient to present certain identity proofing elements.
Expand Down
2 changes: 1 addition & 1 deletion examples/chatbot/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ApiClient, ExpressEventHandler, ApiVersion } from '@2060.io/service-agent-client'
import {
CallOfferRequestMessage,
ContextualMenuSelectMessage,
Expand Down Expand Up @@ -30,7 +31,6 @@ import { Logger } from 'tslog'

import { helpMessage, rockyQuotes, rootContextMenu, rootMenuAsQA, welcomeMessage, worldCupPoll } from './data'
import phoneCredDefData from './phone-cred-def-dev.json'
import { ApiClient, ExpressEventHandler, ApiVersion } from '@2060.io/service-agent-client'

const logger = new Logger()

Expand Down
2 changes: 1 addition & 1 deletion packages/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
},
"dependencies": {
"@2060.io/credo-ts-didcomm-calls": "^0.0.3",
"@2060.io/credo-ts-didcomm-mrtd": "^0.0.8",
"@2060.io/credo-ts-didcomm-mrtd": "^0.0.9",
"@2060.io/credo-ts-didcomm-user-profile": "0.0.6",
"@2060.io/service-agent-model": "*",
"@credo-ts/action-menu": "^0.5.11",
Expand Down
61 changes: 58 additions & 3 deletions packages/main/src/events/MessageEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import {
CallOfferMessage,
CallRejectMessage,
} from '@2060.io/credo-ts-didcomm-calls'
import { EMrtdDataReceivedEvent, MrtdEventTypes, MrzDataReceivedEvent } from '@2060.io/credo-ts-didcomm-mrtd'
import {
EMrtdDataReceivedEvent,
MrtdEventTypes,
MrtdProblemReportEvent,
MrtdProblemReportReason,
MrzDataReceivedEvent,
} from '@2060.io/credo-ts-didcomm-mrtd'
import {
ConnectionProfileUpdatedEvent,
ProfileEventTypes,
Expand All @@ -34,6 +40,7 @@ import {
VerifiableCredentialSubmittedProofItem,
MessageStateUpdated,
MessageReceived,
MrtdSubmitState,
} from '@2060.io/service-agent-model'
import { MenuRequestMessage, PerformMessage } from '@credo-ts/action-menu'
import { V1PresentationMessage, V1PresentationProblemReportMessage } from '@credo-ts/anoncreds'
Expand Down Expand Up @@ -410,18 +417,66 @@ export const messageEvents = async (agent: ServiceAgent, config: ServerConfig) =
agent.events.on(MrtdEventTypes.MrzDataReceived, async ({ payload }: MrzDataReceivedEvent) => {
const { connection, mrzData, threadId } = payload

const msg = new MrzDataSubmitMessage({ connectionId: connection.id, threadId, mrzData })
const msg = new MrzDataSubmitMessage({
connectionId: connection.id,
threadId,
state: MrtdSubmitState.Submitted,
mrzData,
})

await sendMessageReceivedEvent(agent, msg, msg.timestamp, config)
})

agent.events.on(MrtdEventTypes.EMrtdDataReceived, async ({ payload }: EMrtdDataReceivedEvent) => {
const { connection, dataGroups, threadId } = payload

const msg = new EMrtdDataSubmitMessage({ connectionId: connection.id, threadId, dataGroups })
const msg = new EMrtdDataSubmitMessage({
connectionId: connection.id,
threadId,
state: MrtdSubmitState.Submitted,
dataGroups,
})

await sendMessageReceivedEvent(agent, msg, msg.timestamp, config)
})

// MRTD problem reports
agent.events.on(MrtdEventTypes.MrtdProblemReport, async ({ payload }: MrtdProblemReportEvent) => {
const { connection, description, threadId } = payload

const stateMap: Record<MrtdProblemReportReason, MrtdSubmitState> = {
'e.p.emrtd-refused': MrtdSubmitState.Declined,
'e.p.emrtd-timeout': MrtdSubmitState.Timeout,
'e.p.mrz-refused': MrtdSubmitState.Declined,
'e.p.mrz-timeout': MrtdSubmitState.Timeout,
}

if (
[MrtdProblemReportReason.EmrtdRefused, MrtdProblemReportReason.EmrtdTimeout].includes(
description.code as MrtdProblemReportReason,
)
) {
const msg = new EMrtdDataSubmitMessage({
connectionId: connection.id,
threadId,
state: stateMap[description.code as MrtdProblemReportReason],
})
await sendMessageReceivedEvent(agent, msg, msg.timestamp, config)
} else if (
[MrtdProblemReportReason.MrzRefused, MrtdProblemReportReason.MrzTimeout].includes(
description.code as MrtdProblemReportReason,
)
) {
const msg = new MrzDataSubmitMessage({
connectionId: connection.id,
threadId,
state: stateMap[description.code as MrtdProblemReportReason],
})
await sendMessageReceivedEvent(agent, msg, msg.timestamp, config)
}
})

// At the moment we only support refusal/timeouts. Other errors are TBD
}

const sendMessageReceivedEvent = async (
Expand Down
2 changes: 1 addition & 1 deletion packages/model/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"test": "jest"
},
"dependencies": {
"@2060.io/credo-ts-didcomm-mrtd": "^0.0.8",
"@2060.io/credo-ts-didcomm-mrtd": "^0.0.9",
"@credo-ts/core": "^0.5.11",
"class-transformer": "0.5.1",
"class-validator": "0.14.1",
Expand Down
1 change: 1 addition & 0 deletions packages/model/src/messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ export * from './mrtd/MrzDataRequestMessage'
export * from './mrtd/MrzDataSubmitMessage'
export * from './mrtd/EMrtdDataRequestMessage'
export * from './mrtd/EMrtdDataSubmitMessage'
export * from './mrtd/MrtdSubmitState'
export * from './MessageType'
17 changes: 11 additions & 6 deletions packages/model/src/messages/mrtd/EMrtdDataSubmitMessage.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { EMrtdData } from '@2060.io/credo-ts-didcomm-mrtd'
import { Expose } from 'class-transformer'
import * as Mrz from 'mrz'

import { BaseMessage, BaseMessageOptions } from '../BaseMessage'
import { MessageType } from '../MessageType'

import { MrtdSubmitState } from './MrtdSubmitState'

export type EMrtdRawData = {
raw: Record<string, string>
processed: {
Expand Down Expand Up @@ -33,7 +34,8 @@ export type EMrtdRawData = {
}

export interface EMrtdDataSubmitMessageOptions extends BaseMessageOptions {
dataGroups: EMrtdData
state: MrtdSubmitState
dataGroups?: EMrtdData
}

export class EMrtdDataSubmitMessage extends BaseMessage {
Expand All @@ -45,17 +47,20 @@ export class EMrtdDataSubmitMessage extends BaseMessage {
this.threadId = options.threadId
this.timestamp = options.timestamp ?? new Date()
this.connectionId = options.connectionId
this.dataGroups = this.parseDataGroups(options.dataGroups)
if (options.dataGroups) {
this.dataGroups = this.parseDataGroups(options.dataGroups)
}
}
}

public readonly type = EMrtdDataSubmitMessage.type
public static readonly type = MessageType.EMrtdDataSubmitMessage

@Expose()
public dataGroups!: EMrtdRawData
public state!: MrtdSubmitState

public dataGroups?: EMrtdRawData

public parseDataGroups({ raw, parsed }: EMrtdData): EMrtdRawData {
public parseDataGroups({ raw, parsed }: EMrtdData) {
if (!parsed || !parsed.fields) return this.dataGroups

const dataUrls = parsed.fields.images.map(image => {
Expand Down
6 changes: 6 additions & 0 deletions packages/model/src/messages/mrtd/MrtdSubmitState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum MrtdSubmitState {
Submitted = 'submitted',
Declined = 'declined',
Timeout = 'timeout',
Error = 'error',
}
11 changes: 7 additions & 4 deletions packages/model/src/messages/mrtd/MrzDataSubmitMessage.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { MrzData } from '@2060.io/credo-ts-didcomm-mrtd'
import { Expose } from 'class-transformer'

import { BaseMessage, BaseMessageOptions } from '../BaseMessage'
import { MessageType } from '../MessageType'

import { MrtdSubmitState } from './MrtdSubmitState'

export interface MrzDataSubmitMessageOptions extends BaseMessageOptions {
mrzData: MrzData
state: MrtdSubmitState
mrzData?: MrzData
}

export class MrzDataSubmitMessage extends BaseMessage {
Expand All @@ -24,6 +26,7 @@ export class MrzDataSubmitMessage extends BaseMessage {
public readonly type = MrzDataSubmitMessage.type
public static readonly type = MessageType.MrzDataSubmitMessage

@Expose()
public mrzData!: MrzData
public mrzData?: MrzData

public state!: MrtdSubmitState
}
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
class-validator "0.14.1"
tsyringe "^4.8.0"

"@2060.io/credo-ts-didcomm-mrtd@^0.0.8":
version "0.0.8"
resolved "https://registry.yarnpkg.com/@2060.io/credo-ts-didcomm-mrtd/-/credo-ts-didcomm-mrtd-0.0.8.tgz#faf0d24a651957138437f30ff0ff15695256eece"
integrity sha512-l6jDnDOu9yDIobQprCmaJCesUpmd/8AspKKI9KTlNlOFfmms++UcBEcBdQttVbb7KYJawsttoAWbLHJvWBUtfQ==
"@2060.io/credo-ts-didcomm-mrtd@^0.0.9":
version "0.0.9"
resolved "https://registry.yarnpkg.com/@2060.io/credo-ts-didcomm-mrtd/-/credo-ts-didcomm-mrtd-0.0.9.tgz#fb0780c16f4a391ee902c026811a97dcf48013e3"
integrity sha512-KlFhrjdaHDHKDH7zKevBr2H19ueZMSXj/kySd1NixIqiEyZW3hVDzhnu9GjXdO1olezOs80hc9Khu07xWdpdwA==
dependencies:
"@li0ard/tsemrtd" "^0.2.0"
class-transformer "0.5.1"
Expand Down

0 comments on commit 6a16c6a

Please sign in to comment.