decentralized-identity / didcomm-messaging

https://identity.foundation/didcomm-messaging/spec/
Apache License 2.0
160 stars 57 forks source link

SKID: Value or Reference? #191

Closed TelegramSam closed 2 years ago

TelegramSam commented 3 years ago

PR #185 Proposes that Sender Key IDs (SKID) should be a reference.

Historically, we've argued for passing the SKID by Value.

Please articulate your position on this issue, that we can all understand the various opinions and points for this decision.

awoie commented 3 years ago

To clarify what is in #185 :

The PR says both are OPTIONAL but either MUST be used as far as I understood.

Generic JWE/ECDH-1PU implementations considerations:

For privacy reasons, it is probably not a good idea to use skid at all. We should instead use the encrypted_skid (respectively spk or encrypted_spk). I don't know if there are use cases where the plain skid makes sense. If there are use cases, I can live with that as long as we say that encrypted_skid is recommended.

Size considerations:

EIP2844 considerations:

Updated: Even with the encrypted_spk, we would need to provide a link to the public key in the DID Document to verify that the public key belongs to the from DIDComm property. There is also the question, what encoding (e.g., JWK etc.) should be used for the encrypted_spk? IMO, it must be the encoding that is also used in the DID Document. Otherwise, you'd end up with converting public key encodings between each other but in order to allow generic JWE/ECDH-1PU implementations to support DIDComm authcrypt we will probably have to agree on one encoding (e.g., JWK because JWE is JOSE). The conversion of public key encodings makes me a bit nervous.

oed commented 3 years ago

do you expect DID resolution of the DID URI to the sender's key need to happen in the EIP2844 implementation or outside?

Do you mean when decrypting? I would prefer if it happens outside for decryption since it would not be great if wallets needed to support resolving random DID methods. However, this seems less than ideal from a security perspective (a malicious app could send you the wrong public key for the skid. Not sure what implications this would have however.

awoie commented 3 years ago

@TelegramSam I think I got convinced that including the public key material is a good idea but I would argue we are not using skid and encrypted_skid for that but instead use names that tell that the actual public key is included and not a reference, e.g., spk/sender_key and encrypted_spk/encrypted_sender_key.

Mixing up the layering does not make sense for generic ECDH-1PU/JWE implementations. It also makes less sense for the wallet interface that is proposed under EIP2844.

troyronda commented 3 years ago

contains the JWK, then the JWE could become large. If it contains the raw bytes

I think more than raw bytes would be needed as the key type/curve need to be identified. (like in the DID document VerificationMethod itself.)

oed commented 3 years ago

I think more than raw bytes would be needed as the key type/curve need to be identified. (like in the DID document VerificationMethod itself.)

It would really make a lot of sense to use multicodec for this! I.e. the thing that did:key uses to identify a key with a single varint. See DID Key spec

troyronda commented 3 years ago

Even with the encrypted_spk, we would need to provide a link to the public key in the DID Document to verify that the public key belongs to the from DIDComm property.

The from DIDComm property MUST have a clear link with the sender key used in the JWE. Is there already text in the spec defining this link? (there should be).

I believe there were three scenarios mentioned where the key value is useful.

(1) The key value in the DID Document was changed for the DID URI that was used (and versions aren't globally supported). (2) The DID method might not be supported causing a DID resolution failure. (3) Some peer-like DID methods need bootstrapping that isn't within the DID URI.

I'd argue that the first two scenarios can still cause a failure, but at a different layer. As we are using 1PU for sender authentication, the receiver MUST be able to link the from property to the sender key being used. This means that the DID URI needs to be dereferenced and that relationship between from and key verified. i.e., when this can't happen, we have a failure at another layer. With the failure being an authentication issue, do we expect the receiver to send a problem report?

With the third situation, it would be nice if that bootstrapping could have happened in the DID URI (or out-of-band). I think this topic becomes a discussion on how to attach this information (similar to the previous - can't resolve so how do we attach (a subset of) that resolution result with the expectation that it still needs to be validated against the from DID URI at another layer).

In any case, I think we should retain a skid definition as a defined input into 1PU. I think it makes sense for skid/encrypted_skid to be able to resolve the key value (a DID URI). For the case where we effectively want to attach the contents of the resolved VerificationMethod, we should talk about the best way to do that (when needed). I don't think that discussion changes what skid/encrypted_skid is though.

awoie commented 3 years ago

contains the JWK, then the JWE could become large. If it contains the raw bytes

I think more than raw bytes would be needed as the key type/curve need to be identified. (like in the DID document VerificationMethod itself.)

Yep, that is right but with additional context, i.e., type, curve of epk, you would probably have everything you needed. But I'm not arguing for it. Also think more data is better than guessing :)

TelegramSam commented 3 years ago

How about this as a proposal?

baha-ai commented 3 years ago

Both from and to attributes in the inner message are optional. If missing, their value is equal to the DID portion of the corresponding skid/kid in the encryption layer.

In an attempt to prevent key re-use between the encryption layer and the inner message, I suggest removing this statement. Keys for the encryption layer should be sourced from the KeyAgreement DID method ID as kid while the inner message can use the main verification method ID.

andrewwhitehead commented 3 years ago

If you need to send a message to a recipient that will not be able to resolve your DID, a locally resolvable DID method (ex: peer did) MUST be used.

Or send anonymously, right? :)

awoie commented 3 years ago
  • Keys MUST NOT be passed by value in the encryption layer. If you need to send a message to a recipient that will not be able to resolve your DID, a locally resolvable DID method (ex: peer did) MUST be used.

Two questions:

  1. Does this mean that providing the sender public key in the JWE is out of scope of our spec?
  2. How does this address encryption of skid which is needed for privacy reasons?
TelegramSam commented 3 years ago

Keys for the encryption layer should be sourced from the KeyAgreement DID method ID as kid while the inner message can use the main verification method ID.

The kids in the encryption layer refer to keys, while the from and to attributes inside the message refer to DIDs, who's resolved DID Documents would contain both verification and encryption keys. If you agree with this, than I don't think I need to remove that statement at all. Do I understand your argument correctly?

TelegramSam commented 3 years ago

Or send anonymously, right? :)

Yes, but without reinvention of message authentication.

TelegramSam commented 3 years ago

Two questions:

  1. Does this mean that providing the sender public key in the JWE is out of scope of our spec?

It does mean that the sender public key must be resolved, not contained directly. This may be resolved via a DID method that can be resolved locally (did:peer), but does not support inline keys directly.

  1. How does this address encryption of skid which is needed for privacy reasons?

We still need to encrypt the skid to the recipient. (this proposal does not change that need.)

awoie commented 3 years ago

Two questions:

  1. Does this mean that providing the sender public key in the JWE is out of scope of our spec?

It does mean that the sender public key must be resolved, not contained directly. This may be resolved via a DID method that can be resolved locally (did:peer), but does not support inline keys directly.

  1. How does this address encryption of skid which is needed for privacy reasons?

We still need to encrypt the skid to the recipient. (this proposal does not change that need.)

If we assume that skid is encrypted (to recipient) and DID Resolution needs to happen, then what would be the API of a ECDH-1PU decryption lib? I'm concerned that some architectures will need a two-step process where in the first step the JWE needs to be partially decrypted, before the rest of the JWE could be actually decrypted.

The following is a simplified version but it kind of feels weird to have those separate steps. Certainly, you could provide a key resolver instance to the decryptJWE directly (or similar). But in some architectures this might not be possible, e.g., when DID resolution cannot be done by the application that manages the keys (and decrypts the JWE).

const jwe = getNextDidCommMessage(...)

// this will be actually decrypted in another application or context (e.g., remote, different app etc)
const senderDidUri = decryptSkid(jwe, ...)

// tbd: check sender verification method is authorized

const senderPublicKey = resolver.dereferenceUrl(senderDidUri)

// this will be actually decrypted in another application or context (e.g., remote, different app etc)
const message = decryptJWE(jwe, senderPublicKey, ...)

// tbd: check recipient verification method is authorized

This is why I actually think providing the public key by value might makes sense, not only for local DID methods.

TelegramSam commented 3 years ago

@awoie You highlight the difference between the value and ID approaches. I can be happy with either approach, but we should pick one. I'm not a fan of allowing both ID and value approaches. I'm sure that discussion will be plentiful in our meeting today.

awoie commented 3 years ago

Would skid be likely a JWE (JWT)? E.g., Direct Mode (no key wrapping).

troyronda commented 3 years ago

when DID resolution cannot be done by the application that manages the keys (and decrypts the JWE).

DID resolution must occur prior to processing the message.

I can be happy with either approach, but we should pick one. I'm not a fan of allowing both ID and value approaches.

I'm not a fan of the key value approach since the key must be resolvable by ID for message processing anyways.

baha-ai commented 3 years ago

Keys for the encryption layer should be sourced from the KeyAgreement DID method ID as kid while the inner message can use the main verification method ID.

The kids in the encryption layer refer to keys, while the from and to attributes inside the message refer to DIDs, who's resolved DID Documents would contain both verification and encryption keys. If you agree with this, than I don't think I need to remove that statement at all. Do I understand your argument correctly?

Then it's ok, we're on the same page.

bumblefudge commented 3 years ago

👀

kdenhartog commented 3 years ago

Since the did has to specify a particular key, why don't we just place an additional restraint on the didUrl contained within the key to also pass the key by value?

E.g. SKID MUST contain the entire publicKey multicodec encoded that is usedby the sender as a URL parameter. did:example:123#multicodec(publicKey) or did:example:123?key=multicodec(publicKey)&version=3

This is something that @dhh1128 was suggesting should have been done anyways within did-core. Why don't we just use that and then the key can be passed by reference and value at the same time allowing for an implementation to implement this in a variety of different ways.

troyronda commented 3 years ago

@kdenhartog I am against DIDComm attempting to profile how a DID method or DID controller sets their key identifiers.

Also, some DID methods have their own restrictions on the identifier. Sidetree, for example, restricts the length of key identifiers to 50 Base64URL encoded characters.

awoie commented 3 years ago

What about MUST contain the DID URI but MAY also include the sender public key (e.g., as multicodec) in addition?

We would need to agree on some separator between those two fields in the skid. Or we just introduce a new header for the key and register with IANA, e.g., sender_pk. It could be a MUST skid but MAY contain sender_pk in addition.

This would be nice since it would allow implementations that only rely on skid to ignore sender_pk but for implementations that actually use an architecture that decouples DID resolution from KMS, they would try to find sender_pk first to do the decryption.

Update: This approach would at least help those implementers that optimize for those architectures to have a normative reference they can refer to.

kdenhartog commented 3 years ago

@kdenhartog I am against DIDComm attempting to profile how a DID method or DID controller sets their key identifiers.

Also, some DID methods have their own restrictions on the identifier. Sidetree, for example, restricts the length of key identifiers to 50 Base64URL encoded characters.

That's alright, the usage of the key url parameter could be used to perform a lookup based upon the publicKey property rather than based on matching of the id property. The purpose in that url parameter was not to assume that the verification method id will always be equal to the key.

For example did:example:123?key=multicodec(publicKey)#key1 could be used as well to address this concern. Then when dereferencing occurs the query parameter gets dereferenced first based upon the publicKey* parameter and then validated that the fragment matches the dereferenced verification method. If it doesn't then de-referencing fails.

awoie commented 3 years ago

@troyronda @kdenhartog what would be the issue with the approach I described above?

Some JWE profiles even overload encrypted_key with multiple properties, e.g., nonce and value. That would be another option.

TelegramSam commented 3 years ago

This would be nice since it would allow implementations that only rely on skid to ignore sender_pk but for implementations that actually use an architecture that decouples DID resolution from KMS, they would try to find sender_pk first to do the decryption.

Only when receiving a message could implementations ignore sender_pk. Everyone would have to include the sender_pk in addition to the skid when sending.

Questions I have:

kdenhartog commented 3 years ago

@troyronda @kdenhartog what would be the issue with the approach I described above?

Some JWE profiles even overload encrypted_key with multiple properties, e.g., nonce and value. That would be another option.

I'd be alright with this as described.

kdenhartog commented 3 years ago

@TelegramSam here's my take based on conversations with @awoie and @oed this week.

This would be nice since it would allow implementations that only rely on skid to ignore sender_pk but for implementations that actually use an architecture that decouples DID resolution from KMS, they would try to find sender_pk first to do the decryption.

Only when receiving a message could implementations ignore sender_pk. Everyone would have to include the sender_pk in addition to the skid when sending.

I think ignoring the sender_pk could be done when sending as well. It would just require 2 RPC calls to be done. The reason this is a problem is because it also leads to the potential of 2 consent requests in the wallet UI to receive a message.

One alternative is to build the resolver on the RPC server side, but this leads to a misalignment of decisions around trust at the DID layer because the wallet implementors (people who write the RPC server) decide which DID methods for all dApps rather than allowing the dApps to individually decide which DID methods are trusted.

Additionally when the RPC server decides which DID methods to support, it prevents the ability of extending the decision of trust in DID methods to the user which is advantageous to self-sovereignty and decentralization. This is why the resolution shouldn't be done inside the wallet layer to reduce to a single RPC call.

In summation, if necessary skid only can be supported by Ethereum wallets but there's definitive UX hurdles that are created because of it. Hence, @awoie initial hesitation in settling for the currently solution.

Questions I have:

* What is the effect of not supporting keys by value on the Ethereum community? Is it a pain or an absolute show stopper?

It's not an absolute show stopper for all Ethereum wallet implementations, but it does have effects that could require two consent requests to receive a message for some Ethereum wallets are implemented today. This is because some wallet implementations require consent be gather at the UI layer before allowing access to the key. This in my eyes is borderline absolute show stopper.

* If including the `sender_pk` is necessary, can we be smart about when it's required? Maybe send initially, and stop if you confirm the other side doesn't need it. Can we use an error back to sender to indicate the need for the `sender_pk` if a message is received without it?

It's not necessary, but is an advantage for both dev UX and user UX in some implementations. Hence, @awoie being alright with MAY language. It allows them to build better UX when interacting within the Ethereum dApp ecosystem who want to optimize, but doesn't prevent broad interop still.

* If this is really an effort to make it easier for a potentially large community to participate, who among us is willing to take this extra step?

I think this is why @awoie option may be better than mine, it doesn't require participation to get interop, but it does help. Mine on the other hand requires implementation (while also not requiring key looping).

awoie commented 3 years ago

@kdenhartog Thanks for the great summary.

Having no option to include the key by value will be a show stopper because the UX would be not great. However, for those cases where an agent does not send the key by value and only by reference, we would be still interoperable. For "ETH-agent" to "ETH-agent" I assume that we would always send both, skid and key by value to have better UX. How the key is actually encoded (new field, inside existing field + separator) is flexible.

TelegramSam commented 3 years ago

WG 20210524 - Consensus that an optional (for both sender and receiver) field will work. Kyle to work on PR.

kdenhartog commented 3 years ago

I saw this on my TODO list but couldn't remember the deeper context for it. Found it and assigned it to myself.

baha-ai commented 3 years ago

I believe the safest more general kid/skid values we can use are did:key representations as per Aries RFC 360

andrewwhitehead commented 3 years ago

did:key does not seem conducent to verifying the identity of the sender. I believe would mean performing some version of key equality testing between what is in the sender's DID document (possibly a JWK) and the multibase version of the key, and this would need to be formalized for the supported key types. If the skid is simply a reference to a key in the document then this would not be required.

kdenhartog commented 3 years ago

Yeah isn't using a did:key effectively like a different identifier? Are you planning to use alsoKnownAs or something with that method @Baha-sk? I was under the impression we'd put the did-url that matches the key inside the kid property and that needs to be matched to the id property in the did document.

baha-ai commented 2 years ago

did:key does not seem conducent to verifying the identity of the sender.

although we aim to identify the sender in the end, the skid's purpose is for identifying the key itself. The nice thing about did:key is it's self identifying and the public key can be extracted from it directly. With the did:key, we don't need an additional step for key equality testing.

The other nice thing is if the key changes, did:key will change accordingly. So no need to check for versions, or translate to JWKs. The JWE logic doesn't need to be aware of DID specific relationship with the keys, it will only deal with string values in skid/kid.

Yeah isn't using a did:key effectively like a different identifier? Are you planning to use alsoKnownAs or something with that method @Baha-sk? I was under the impression we'd put the did-url that matches the key inside the kid property and that needs to be matched to the id property in the did document.

Originally, I had the same thought @kdenhartog, which is using the did-url key identifier in KeyAgreement's ID. I was thinking to simply use the same values as-is in the jwe envelope to reduce identifier translation between the envelope and the DID doc. But since KeyAgreement's IDs can have relative did-url values starting with #, having a skid/kid value looking like #keys-1 doesn't tell much about the key ID, it will require an additional header for the DID reference.

While if we use did:key representation in skid/kid header, an app can easily compare its value against the service bloc and also extract the public key directly.

kdenhartog commented 2 years ago

Hmm, I think I'm lost and it seems similar to @andrewwhitehead question as well. So if I trust did:example:123 and the associated keys, how am I able to know that the message was sent by did:example:123 if the skid is of did:key?

Originally, I had the same thought @kdenhartog, which is using the did-url key identifier in KeyAgreement's ID. I was thinking to simply use the same values as-is in the jwe envelope to reduce identifier translation between the envelope and the DID doc. But since KeyAgreement's IDs can have relative did-url values starting with #, having a skid/kid value looking like #keys-1 doesn't tell much about the key ID, it will require an additional header for the DID reference.

I don't understand why we'd need to pass #referenceFragment. Wouldn't we instead pass did:example:123#referenceFragment and then a dereferencer would perform the mapping between did:example:123#referenceFragment and #referenceFragment which is contained in the did document of did:example:123.

dhh1128 commented 2 years ago

how am I able to know that the message was sent by did:example:123 if the skid is of did:key?

+1 to this question. It feels important to me.

awoie commented 2 years ago

+1, DID URL approach, i.e., skid=did:example:123#key-1 -1, did:key approach, i.e., skid=did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH - In the worst case, i'd need to convert each public key material in the sender's DID Doc and compare against the did:key. In the DID URL approach, I'd only need to convert once (max). It also feels weird to have different identifiers for skid and from(if provided).

baha-ai commented 2 years ago

@kdenhartog, @dhh1128, @awoie

first: the didComm service bloc in the DID doc uses did:key for recipientKeys/senderKey. At the encryption envelope layer, we should just follow suit for packing the JWE envelopes (this Aries RFC explains the reasons behind it, cc @swcurran).

second: requiring dereferencing keys to the DID doc means the encryption layer needs to be aware of the DID doc. Using did:key makes it easier to work with keys independently. DIDComm frameworks should be able to provide did:key -> raw key translations anyway. You have a valid concern about how to validate ownership of the key in the DID doc, but i believe this should be done at a higher level that handles the payload content. ie: now my envelope was successfully decrypted, does my payload correspond to data in myDID/theirDID/oob invitation/DID connection. In fact oob invitations don't have DIDs yet, so linking to a DID makes DIDComm unworkable for these types to requests.

So to make things simple, encrypt/decrypt using did:key and once decrypted, a higher level layer can verify the did:keys in the kid field exists in the DIDcomm service bloc of the DID doc/connection or are part of the oob request in case of no DIDs exchanged yet.

third: this is for @awoie about skid and kid formats. We should have the same format for both headers. What is really weird is having the encryption layer meddling with the DID doc ID if it's a fragment (eg #key-1), then append the DID url: (did:peer:abc#key-1). To avoid this confusion and versioning of keys issues, using did:key guarantees ID consistency across the board.

The question I have for you is: do the encryption layer really require dereferencing skid/kid and validating these values with DID doc VM IDs? or should the higher layer handle this verification? And what to do for requests that don't have a DID connection yet (like oob invitations)?

IMHO, the encryption layer should just handle encryption/decryption using provided keys and kid/skid values with minimum translation possible from the rest of the DID docs and connections involved. Once the envelope is decrypted, the payload receiver at higher level can do additional checks as needed. I have been trying to find a proper solution to this problem for the last couple of weeks and using did:key was the one that makes most sense as i was implementing this change in AFGO.

If you think my suggestion is offtrack, please let me know. I intend to update the DIDcomm docs with using did:key values in kid/skid and we can probably discuss this issue during next Monday's community meeting as it's urgent for completion of V2 interop.

andrewwhitehead commented 2 years ago

@Baha-sk I appreciate the convenience of the encryption layer being able to unpack the message without resolving a DID document first, and I think that's worth exploring more, as it could be good for performance and the separation of layers if it can be implemented without sacrificing security or introducing too much complication in the next layers. However..

So to make things simple, encrypt/decrypt using did:key and once decrypted, a higher level layer can verify the did:keys in the kid field exists in the DIDcomm service bloc of the DID doc/connection or are part of the oob request in case of no DIDs exchanged yet.

This does not seem like an acceptable form of authentication, because it's ignoring the authentication mechanisms that the DID document already provides.

I also personally don't like the dependence on the did:key standard. Although it's convenient in that it's already specified, if the public key is to be encoded inline then that format should be specified by DIDComm itself or a closely adjacent specification.

dhh1128 commented 2 years ago

first: the didComm service bloc in the DID doc uses did:key for recipientKeys/senderKey

That's the DIDComm v1 service block. We are not bound by it.

I also personally don't like the dependence on the did:key standard. Although it's convenient in that it's already specified, if the public key is to be encoded inline then that format should be specified by DIDComm itself or a closely adjacent specification.

+100.

baha-ai commented 2 years ago

@andrewwhitehead @dhh1128 how can we handle oob invitations then where DIDs are still not exchanged? ie there's no DID yet to dereference the kid/skid in this case.

baha-ai commented 2 years ago

first: the didComm service bloc in the DID doc uses did:key for recipientKeys/senderKey

That's the DIDComm v1 service block. We are not bound by it.

@dhh1128 can you point me to where this is mentioned in the docs ?

awoie commented 2 years ago

@Baha-sk please find some comments below ...

@kdenhartog, @dhh1128, @awoie

first: the didComm service bloc in the DID doc uses did:key for recipientKeys/senderKey. At the encryption envelope layer, we should just follow suit for packing the JWE envelopes (this Aries RFC explains the reasons behind it, cc @swcurran).

Please find the DIDComm Messaging (v2) service block here: https://identity.foundation/didcomm-messaging/spec/#did-document-service-endpoint.

second: requiring dereferencing keys to the DID doc means the encryption layer needs to be aware of the DID doc. Using did:key makes it easier to work with keys independently. DIDComm frameworks should be able to provide did:key -> raw key translations anyway. You have a valid concern about how to validate ownership of the key in the DID doc, but i believe this should be done at a higher level that handles the payload content. ie: now my envelope was successfully decrypted, does my payload correspond to data in myDID/theirDID/oob invitation/DID connection. In fact oob invitations don't have DIDs yet, so linking to a DID makes DIDComm unworkable for these types to requests.

OOB messages are plaintext and can (should?) have a from property (a DID). See example in the current DIF DIDComm Messaging spec. Unfortunately, the OOB section has two examples. The first one seems to be broken and we should fix that.

So to make things simple, encrypt/decrypt using did:key and once decrypted, a higher level layer can verify the did:keys in the kid field exists in the DIDcomm service bloc of the DID doc/connection or are part of the oob request in case of no DIDs exchanged yet.

I also think that the higher layer should verify that and not the encryption layer. I'd assume that the higher layer provides the resolved/dereferenced keys to the encryption layer. I just don't see the benefit of using a DID method (did:key) that is potentially different from the from/to DID method.

third: this is for @awoie about skid and kid formats. We should have the same format for both headers. What is really weird is having the encryption layer meddling with the DID doc ID if it's a fragment (eg #key-1), then append the DID url: (did:peer:abc#key-1). To avoid this confusion and versioning of keys issues, using did:key guarantees ID consistency across the board.

As mentioned above, I agree and I don't think that dereferencing the DID URL should be done by the encryption layer. But I don't see the need to use did:key:alicekey instead of did:example:alice#key when did:example:alice is used for from. It just makes the key auth process harder (i.e., checking whether key is authorized by DID).

Further, if did:key was used for kid/skid, and you translate those in the encryption layer, it means, you'd also need DID resolution on that layer anyways.

The question I have for you is: do the encryption layer really require dereferencing skid/kid and validating these values with DID doc VM IDs? or should the higher layer handle this verification? And what to do for requests that don't have a DID connection yet (like oob invitations)?

IMO, the encryption layer does not care about kid and skid at all. You'd need to find the keys one layer above (based on kid/skid) and provide those to the encryption layer.

baha-ai commented 2 years ago

Thank you @awoie for the detailed response. Indeed, we have some work to do to remove RecipientKeys from the service bloc in this case to be DIDComm V2 compatible.

DID url it is then.. i need to double check what needs to be done for oob invitations though.

awoie commented 2 years ago

@TelegramSam I guess we can close this issue?

awoie commented 2 years ago

Closing this issue since discussion happens in #219