Several questions about storage & secure storage in monday-code-sdk

I’ve been reading the docs about the monday-code-sdk and have a few questions…

Segregation of storage & secure storage

In Storage, data:

is segregated according to the accountId and app, so data stored by one account is inaccessible by other accounts to provide an additional layer of security.

So far, so good. This all seems quite reasonable.

And in monday terminology, an account is the instance of monday, or tenant, easily identified by a unique origin e.g. https://myexampleaccount.monday.com

In Secure Storage:

The secureStorage method stores sensitive customer data for monday-code projects. The data is stored securely and logically segregated, meaning it is stored in smaller categories on the same device to easily grant or block access. It is segregated for your specific app, so data stored by one app is inaccessible by other apps to provide an additional layer of security.

:point_right: Question 1. The sentence below seems a bit vague. Could this be expanded upon in the documentation please?

The data is stored securely and logically segregated, meaning it is stored in smaller categories on the same device to easily grant or block access.

:point_right: Question 2. It doesn’t explicitly say in the docs, but can we confirm that secure storage is also segregated according to the accountId as well as the app?

Data retention policy for storage & secure storage

I’m trying to understand what the lifecycle is for storage & secure storage.

Scenario

Let’s say that a developer builds an app which stores some kind of access token for an external system within secure storage on behalf of each user of monday.com who is also a user of the external system.

While the app remains installed, the developer can allow users of the app to delete their access token from secure storage, whereby the app will no longer have access to the external system.

In time, the app is uninstalled and the reinstalled. Later, the app is uninstalled, but this time for good.

:point_right: Question 3. What happens to the access tokens saved within secure storage?

  • I would hope that the data is not immediately removed on uninstall as that would break the app if it was subsequently reinstalled.
  • I would also hope that the data does not live forever within monday, and that after a stated period of time, the data for the app would be removed.

:point_right: Question 4. What is the data retention policy for data from apps which have been uninstalled?

This information should be added to the docs so that app developers have somewhere to point their customers to when it inevitably is requested.

– Thanks for reading, David.

1 Like

Hey @dvdsmpsn,
Great topic and thank you for bringing this up for clarification. I’ll try to answer your questions one by one:

  1. About the secure storage - indeed, the documentation here is a bit confusing (we will refine it, sorry for the inconvenience), there’s no segregation for it per account. The secure storage is entirely in your control, you can store there what you want and how you want, and you are fully responsible on this data. We do recommend to use it primarily for user tokens (in case your app is doing oAuth that allow you to communicate with other services, such as our storage, our public api or 3rd party services). BTW, we have an example on how everything plays out here: welcome-apps/apps/github-monday-code at master · mondaycom/welcome-apps · GitHub

  2. As mentioned above - it is not

  3. As you would imagine - nothing happens, you have full control over your secure storage and we do not delete data from storage. So if someone uninstalls and then later installs again, all data should be there (unless you’re segregating the data according to some internal ID that you manage, in this case - it’s your business logic :man_shrugging:).

  4. About data retention policy - this is a great question.
    4a. Secure storage - it’s kept there forever as you have full control over this storage and we don’t really have a simple way of accessing to it. You are expected to delete the tokens there as soon as the admin removes your app from the account (though we’re also invalidating them on our side)
    4b. Applications storage - we do not delete that data but have protocols in place to remove it upon request, segregated by account id. The way it works is that a customer may reach out to you and ask you to remove their data. In this case you will open a ticket on our side and within a reasonable SLA, we will remove that data

Hopefully this is helpful

Greg

HI @gregra, so what you’re really saying about secure storage is this is a big bucket that I can store user tokens in, in any way I desire.

That’s interesting, but leads to further questions.

Preventing clashes of keys

Say a developer uses a key to store (examples 1):

  • monday.user.${userId}.oauth.token.external.system – based on user
  • monday.board.${boardId}.oauth.token.external.system – based on board
  • monday.item.${itemId}.oauth.token.external.system – based on item

:point_right: Question 1: As board ids and item ids are not unique between accounts, would you be recommending that we store with keys more like this (examples 2):

  • monday.account.${accountId}.user.${userId}.oauth.token.external.system – based on user
  • monday.account.${accountId}.board.${boardId}.oauth.token.external.system – based on board
  • monday.account.${accountId}.board.${boardId}.item.${itemId}.oauth.token.external.system – based on item

:point_right: Question 2: What key format would you recommend to ensure that everything is unique for all accounts, users, boards, items etc?

Removal of data

If a developer needs to delete all data for an app for a particular account;

  • :point_right: Question 3: How would a developer find all the keys in example 2 and then remove them from secure storage if they don’t know every userId, boardId or itemId?
  • :point_right: Question 4: If the user uninstalls the app, then reinstalls it, we’d expect the tokens to remain, but then cleanup after a stated period of time if the app remains uninstalled. How would a developer achieve this “after the fact” data deletion?
  • :point_right: Question 5: Would monday•com be able to remove the items with keys in the formats for example 1, or for example 2 (above)?

For both q1 and q2 - no strong opinions here, other than the fact they should be unique on the account level, as you already mentioned. i.e. accountId should be in all keys for sure. The other part of the key really depends on the use case (again, no strong opinions on my part).

Removal of data
q3: Good question - I recommend that you store another key with account id only that stores all the other keys (i.e. “index”)
q4: Using the above mechanism + storing some timestamp in secure storage about it. I know it’s not perfect, we’re constantly working on improving our approach
q5: it’s problematic to do it with secure storage as we don’t have a direct access to your secure storage and also no idea on the format of the keys

@gregra

I think I’m hearing that if a developer stores user tokens in secure storage with keys in the following format…

  • monday.account.${accountId}.user.${userId}.oauth.token.external.system – based on user
  • monday.account.${accountId}.board.${boardId}.oauth.token.external.system – based on board
  • monday.account.${accountId}.item.${itemId}.oauth.token.external.system – based on item
  • monday.account.${accountId}.automation.${automationId}.oauth.token.external.system – based on some kind of automation
  • monday.account.${accountId}.webhook.${webhookId}.oauth.token.external.system – based on webhooks
  • monday.account.${accountId}.something.else.${somethingElseId}.oauth.token.external.system – based on something else :person_shrugging:

…then all keys will be unique?

And in order to successfully clean up all the tokens for all the use cases above, then the developer will need to also create a master list/index of all the keys that have been created.

This could be stored in another secure storage item with key:

monday.account.${accountId}.index

And a value like so:

{
  users: [ userId1, userId2, ... ],
  boards: [ boardId1, boardId2, ... ],
  items: [ itemId1, itemId2, ... ],
  automations: [ automationId1, automationId2, ... ],
  webhooks: [ webhookId1, webhookId2, ... ],
  somethingElse: [ somethingElseId1, somethingElseId2, ... ]
}

Is there the potential for this index to get too big for the secure storage?

The developer could then use an Account Settings View to allow an account admin to delete all the tokens based upon tranversing the various IDs in the index and calling secureStorage.delete(keyBasedOnId) for each ID in the index.

This would mean:

  1. All tokens can be accounted for and deleted
  2. The token deletion becomes self service for the account admin before the app is uninstalled.
  3. We could even send an email on uninstall webhook to tell them how to clean up their tokens if they haven’t already.

The Account Settings View would need to be visible for accounts who no longer have a valid subscription. Is this possible?

I think that I like this approach best because it puts the onus on the customer to delete their own tokens (because it’s easier for them to do so) rather than asking the developer or monday•com to do the job.

@dvdsmpsn So, we had an internal conversation in the team, and it seems that there are limitations that you can hit with storing this index. Sorry for taking the time, we did not come to a conclusion and did not want to keep it without a response.
Anyway, we need some more time in the team to figure out the way forward, and I hope to provide an update as soon as we have a concrete suggestion

Greg

1 Like

@dvdsmpsn so after we talked about it internally, we decided that we will add a way to store tokens on a tenant level (account id), sometimes during Q2. In the meantime, you can use the conventions you described above and in the (rare) case when a customer will ask you to delete their data, you’ll need to open a support ticket with us and we’ll do it (according to your convention) manually.

1 Like

Hey @gregra, thanks for this.

I’ve actually created the index object, so for smaller instances, referencing the index object will allow me to loop through the stored tokens.

This means we can have an Account Settings screen like so:

For larger accounts, this may not work well, so we’ll need to contact support in those instances.

Also, potentially you could add a method to SecureStorage:

import { SecureStorage } from '@mondaycom/apps-sdk';

const secureStorage = new SecureStorage();
secureStorage.deleteLike("monday.account.ABC123.user.*");

…which would delete all items with keys that start with

monday.account.ABC123.user.

I’m not set on the syntax, more sharing an idea.

Yeah, I like that direction and I think you can stick to that. For future reference we will also support supplying the account ID directly through the SDK, so that you will be able to perform account level operations

1 Like

Is they account ID basically going to be a secondary key? Would it be conceivable to specify BOTH keys in SecureStorage then? That way we can specify the account, and then an item key. The composite key acts as the unique value though.

Esp. if you could allow the second key after the account to be queried with a “begins_with” operator, so we could retrieve not just all records for an account but just those prefixed a certain way.