Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document type repository #401

Closed
davidz25 opened this issue Oct 31, 2023 · 5 comments · Fixed by #419 or #436
Closed

Document type repository #401

davidz25 opened this issue Oct 31, 2023 · 5 comments · Fixed by #419 or #436

Comments

@davidz25
Copy link
Contributor

Right now the knowledge of different mdoc document types, their namespaces, and data elements is encoded in both the wallet (in wallet/documentdata/Request*.kt) and in the reader (in document/Request*.kt). We should have a couple of simple classes in the library that both apps can use.

There should be a DocumentTypeRepository which can be used to query available document types, returns instances of DocumentType. The DocumentType class should contain namespaces / data elements specific to the doctype. For each data element, there should be a human-readable localized name (e.g. "Driving Privileges" vs driving_privileges) and there should be room to add things like icons, descriptions, and other things for each data element. For example, we need the the human-readable name for the Android Credman integration in Issue #353.

@davidz25
Copy link
Contributor Author

davidz25 commented Nov 7, 2023

So I think what I had in mind was something like this (pseudo-code):

class DocumentTypeRepository
 addDocumentType(DocumentType type)
 List<DocumentType> getDocumentTypes()

class DocumentType
 String getDisplayName()
 List<DocumentAttribute> getAttributes()
 # Returns null if there's no mdoc DocType for this document type
 MdocDocumentType? getMdocDocumentType()

class DocumentAttribute
 DocumentAttributeType getType()
 String getIdentifier()
 String getDisplayName()
 String getDescription()

enum DocumentAttributeType
 STRING
 NUMBER
 DATE
 DATE_TIME
 PICTURE

which is not dependent on mdoc-format at all which is important in the context of Issue #402. For each credential format we would have companion classes e.g. MdocDocumentType with format-specific content:

class MdocDocumentType
 String getDocType()
 List<MdocNamespace> getNamespaces()

class MdocNamespace
 String getName()
 List<MdocDataElement> getDataElements()

class MdocDataElement
 String getName()
 DocumentAttribute getDocumentAttribute()

which includes the mapping back to the generic document for each data element. With this in hand, we can automate the "add new self-signed credential" screens insofar that the UI can be generated entirely from a DocumentType instance.

Open questions

  • How do we nicely define the four known formats we have today?
    • I guess this would be some code with helps to build up a DocumentType instance for each document type
  • How do we nicely define example data for each known format?
    • E.g. Erika Mustermann for mDLs
  • How do we nicely define common reader requests?

It would also be nice to have something like W3CVerifiableCredentialDataModel similar to MDocDocumentType which would reference https://w3c-ccg.github.io/vdl-vocab/ but I'm not sure how that should look. It would be good to think about that.

@davidz25
Copy link
Contributor Author

davidz25 commented Nov 7, 2023

We probably also want to think more about DocumentAttributeType ... I imagine it could include enumerations and limits/ranges (for both NUMBER and STRING), things like ISO 3166-1 country codes, etc. I think this can be done in a v2 and the list in the previous comment is a good start...

@keesgeluk
Copy link
Contributor

Maybe we should have a common base class for different document types. Is an mdoc document part of a bigger non-mdoc document that has also non-mdoc attributes? Or is an mdoc a specific type of document? If mdoc is a specific type of document, maybe the following proposal would work:

enum class DocumentAttributeType {
    STRING,
    NUMBER,
    DATE,
    DATE_TIME,
    PICTURE,
    BOOLEAN
}

/**
 * Base for any document attribute
 */
interface DocumentAttribute {
    val type: DocumentAttributeType
    val identifier: String
    val displayName: String
}

/**
 * mDoc specific document attribute. Note that the namespace is taken as a property of the data element
 */
interface MdocDataElement : DocumentAttribute {
    val namespace: String
}

/**
 * Interface for document types
 */
interface DocumentType<T> where T : DocumentAttribute {
    val displayName: String
    val dataItems: List<T>
}

/**
 * Example of a non-mDoc document
 */
class SampleDocumentType : DocumentType<DocumentAttribute> {
    override val displayName: String = "Sample document"
    override val dataItems: List<DocumentAttribute> = Attribute.values().asList()

    enum class Attribute(
        override val type: DocumentAttributeType,
        override val identifier: String,
        override val displayName: String
    ) : DocumentAttribute {
        SAMPLE_STRING(DocumentAttributeType.STRING, "sampleString", "My String"),
        SAMPLE_BOOLEAN(DocumentAttributeType.BOOLEAN, "sampleBoolean", "Sample Boolean")
        // Etc.
    }
}

/**
 * Base for all mDocs
 */
abstract class MdocDocumentType : DocumentType<MdocDataElement> {
    abstract val docType: String

    /**
     * Namespaces are read from the data elements
     */
    val namespaces: List<String> = dataItems.map { it.namespace }.distinct()

    /**
     * Get the data elements of a specific namespace
     */
    fun getDataElementsByNamespace(namespace: String): List<MdocDataElement> {
        return dataItems.filter { it.namespace == namespace }
    }
}

/**
 * Concrete implementation for MDL
 */
object MdlDocumentType : MdocDocumentType() {
    override val displayName: String = "Driving License"
    override val dataItems: List<MdocDataElement> = DataElement.values().asList()
    override val docType: String = DocType.MDL

    enum class DataElement(
        override val type: DocumentAttributeType,
        override val identifier: String,
        override val displayName: String,
        override val namespace: String
    ) : MdocDataElement {
        FAMILY_NAME(DocumentAttributeType.STRING, "family_name", "Family Name", Namespace.MDL),
        GIVEN_NAMES(DocumentAttributeType.STRING, "given_name", "Given Names", Namespace.MDL),
        // Etc.
    }
}

/**
 * The document type repository
 */
object DocumentTypeRepository {

    private var documents: List<DocumentType<*>> = ArrayList()
    fun addDocumentType(documentType: DocumentType<*>) {
        documents = documents.plus(documentType)
    }

    fun getDocumentTypes(): List<DocumentType<*>> {
        return documents
    }
}


@davidz25
Copy link
Contributor Author

I must admit I'm not a fan of the inheritance and I don't think it really gives us anything tangible except for extra complexity. Crucially, I also don't think it supports the case where we define an abstract DrivingLicense document type that has two concrete formats, one for the mdoc data model and one for the W3C data model. I also don't think it also e.g. the mdoc data model to have more stuff than what you have in the W3C VC data model.

Thinking more about it we should probably also use the word Credential instead of Document so the class hierarchy would be

class CredentialTypeRepository
 addCredentialType(CredentialType type)
 List<CredentialType> getCredentialTypes()

class CredentialType
 String getDisplayName()
 List<CredentialAttribute> getAttributes()
 # Returns null if there's no mdoc DocType for this Credential type
 MdocCredentialType? getMdocCredentialType()
 VcCredentialType? getVcCredentialType()

class CredentialAttribute
 CredentialAttributeType getType()
 String getIdentifier()
 String getDisplayName()
 String getDescription()

enum CredentialAttributeType
 STRING
 NUMBER
 DATE
 DATE_TIME
 PICTURE

with specializations MdocCredentialType, VcCredentialType and so on.

@keesgeluk
Copy link
Contributor

keesgeluk commented Nov 14, 2023

Thanks, I misunderstood the previous proposal, thought that the mdoc version and the W3C VC version would be a different instance of documenttype/credentialtype...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants