Skip to content

RFC: Optional dotNsIdentifier and permissioned external-account access#245

Draft
valentinfernandez1 wants to merge 2 commits into
mainfrom
vf/rfc-dotNs-remove
Draft

RFC: Optional dotNsIdentifier and permissioned external-account access#245
valentinfernandez1 wants to merge 2 commits into
mainfrom
vf/rfc-dotNs-remove

Conversation

@valentinfernandez1

@valentinfernandez1 valentinfernandez1 commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

The account, signing, and statement-store calls that operate on a product account take a
ProductAccountId { dotNsIdentifier, derivationIndex }, and dotNsIdentifier is optional.

  • Omit it and the call addresses the caller's own product. The host resolves the domain from the
    authenticated caller, so the common case only needs a derivationIndex.
  • Supply a domain that names a different product and the call is cross-product access, gated behind a
    new ExternalAccount remote permission. Like ChainSubmit and StatementSubmit, it is triggered
    implicitly the first time a product makes such a call, and the host accepts or rejects based on the
    grant.
// Own account, the common case
await truapi.account.getAccount({ productAccountId: { derivationIndex: 0 } });

// Another product's account, requires the ExternalAccount permission
await truapi.account.getAccount({
  productAccountId: { dotNsIdentifier: "another-product.dot", derivationIndex: 0 },
});

Host-side enforcement of the ExternalAccount permission lives in the host and is not part of this
change. This PR defines the wire types, the permission variant, and the trait documentation.

Drop dotNsIdentifier from the seven local account, signing, and
statement-store request bodies, callers pass only derivationIndex and
the host resolves the caller's own domain.
@valentinfernandez1

Copy link
Copy Markdown
Collaborator Author

Keeping as draft for now as this is a big breaking change and we need to settle on the best versioning strategy for this

@valentunn

Copy link
Copy Markdown
Contributor

The dotNsIdentifier is present there intentionally: some products are interested in requesting accounts of other products

Hard NO from my side

@valentinfernandez1

Copy link
Copy Markdown
Collaborator Author

Thanks for the feedback @valentunn, I was not aware of this requirement since in general we want per product isolation.

Still part of my design still applies, I invite you to read though the issue as this is not necessarily removing it but rather removing it from these calls and creating explicit permissioned calls for products that want to access the user's account in another product.

So if a product wants to access an account that is not from its on product it must be first explicitly be granted permission by the user

@valentinfernandez1

Copy link
Copy Markdown
Collaborator Author

I will refactor this draft though as I realized that there is a simpler way to approach this by keeping the dotNsIdentifier (maybe make it optional) and if the dotNsIdentifier is different from the one on the current product the host can accept or reject the call depending on whether the user has provided ExternalAccountAccees permission (new permission to be added here)

@valentinfernandez1 valentinfernandez1 changed the title RFC: Remove dotNsIdentifier from default account access RFC: Optional dotNsIdentifier and permissioned external-account access Jul 1, 2026
@valentinfernandez1

Copy link
Copy Markdown
Collaborator Author

Refactoring is done, I have also updated the title and description of this Draft to reflect the updated behavior

Comment on lines +69 to +73
```rust
struct ProductAccountId {
dot_ns_identifier: Option<String>,
derivation_index: u32,
}

@pgherveou pgherveou Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

maybe should be an enum for clarity ?

enum ProductAccountId {
    Current {
        derivation_index: u32,
    },
    Other {
        dot_ns_identifier: String,
        derivation_index: u32,
    },
}

@valentunn valentunn Jul 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Both option and enum looks too specific for such a general purpose type: both approaches effectively forbird usage of ProductAccountId in a context where "current" is not defined

@valentinfernandez1

valentinfernandez1 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

@valentunn is the requirement for requesting other product accounts only for reading or signing too?

As discussed today I will create twin methods that explicitly request for external account (like getExternalAccount or getExternalAccountAlias), should we also include the same for signing? This way getAccount and getAccountAlias would only require a derivationIndex.

@valentunn

valentunn commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

I thought we discussed in the meeting and then explicitly summed up at the end, that option is not needed for dot_ns_identifier in ProductAccountId and instead this RFC should focus on two things:

  1. New permission type for cross-product account access
  2. A new host call to resolve the product's own product id

(2) allows to build more convenient APIs on top while also being usefull for products in other cases

Making dot_ns_identifier nullable / enum would just make the API more complex and provide no real benefit imo

Also,

As discussed today I will create twin methods that explicitly request for external account

This looks opposite to what we discussed actually

@valentunn

Copy link
Copy Markdown
Contributor

About cross-product signing: yes, we generally want to allow all cross-product actions. We only want to limit something to the current product if the action doesn't make much sense in cross-product context, like deriving an entropy for a different product

@valentinfernandez1

valentinfernandez1 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

I thought we discussed in the meeting that option is not needed for dot_ns_identifier in ProductAccountId and instead this RFC should focus on two things:

1. New permission type for cross-product account access

2. A new host call to resolve the product's own product id

(2) allows more convenient APIs be built upon while also being usefull for products in general

Making dot_ns_identifier, as we discussed on the meeting, would just make the API more complex and provide no real benefit

Yes, the permission part is already in this draft (ExternalAccount), and I'll add the host call to resolve the product's own product id, agreed that's useful beyond this RFC. Also agreed on dropping Option, ProductAccountId stays {dotNsIdentifier, derivationIndex}, exactly as today.

On the method shape I think we walked out with different takeaways, so let me make the case here instead. getAccount({ derivationIndex }) addresses the calling product, getExternalAccount({ productAccountId }) is the explicit cross product path and the only method that can trigger the ExternalAccount prompt.

With the required field and the new method getProductId(), every product needs boilerplate (either hardcode the domain or fetch it at startup and pass it through every call) when in reality most products won't need it. The Cross-product access is the exception, so it should carry the extra argument, not the default path.

With the twin methods the only cost is a breaking change to the seven request types plus two new methods, which is not a big issue at the moment.

@valentunn

valentunn commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

I see no benefit in having getAccount or getExternalAccount. First and foremost, it contradicts our main goal of keeping API simple but powerfull. Two separate methods for two different cases looks like a misplaced facade to me. When the base API is generic, you can then define helper functions on top and achieve the same API without making base API more complex

With the required field and the new method getProductId(), every product needs boilerplate

This is not true. TruAPI is not aiming for a perfect devEX it is aiming for completness and ability to have perfect devEx, which itself should be provided by product-sdk.

So overall I get what the point you re trying to address. My take is that you are trying to address it on the wrong level

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants