at_client_sdk
at_client_sdk copied to clipboard
Being able to get an AtClient without having connectivity to your atServer (i.e offline access)
Is your feature request related to a problem? Please describe.
The problem could be that you have an application that has data which has been synched to your device but now the device is offline. With the current SDK although the data is available locally you cannot get to it as you are offline.
This kills a number of use case for instance atBuzz only works if you have an Internet connection.
Describe the solution you'd like
If the atSign has already synched at least once then return an atClient that can read/write locally and when the atServer is not reachable.
Describe alternatives you've considered
none
Additional context
This is important for both flutter and dart apps
@sitaram-kalluri If you're looking for what to pick up next, I'd suggest this one
@sitaram-kalluri If you're looking for what to pick up next, I'd suggest this one
@gkc: Sure, I will start on this. Thank you.
Following are the scenarios with expected behaviour when starting atClient in offline mode:
- When the network is down and atSign is onboarded, Should the user be notified that sync and notification services will not run until the network is back?
Approach - 1: Introduce offline mode
- A caution that atClient is started in offline mode. When in offline mode, the following is the behaviour of the atClient:
- The "put" operation can be allowed with a caution that "Network is down and data will be synced/notified to server once the network is back"
- The notification service will NOT be functional
- The sync service will NOT be functional
- Look-Up for the keys of other atSign are NOT allowed (lookup/plookup verb is NOT allowed. Only LLookup verb is allowed to fetch data in local secondary)
- A caution that atClient is started in offline mode. When in offline mode, the following is the behaviour of the atClient:
- If the client is onboarded in offline mode and if the server is reset, what should be the behaviour on the client side after the network is restored?
Approach - 1
- If the client is onboarded on an offline mode, keep polling on the network, Once the network is back, fetch the encryption public key from the server and compare it with the client. If the value does not match, stop the SDK services and provide an option to unpair the atSign which clears the local storage.
Re (1) : I think we should do as little as possible (ideally nothing) over and above the bare minimum of making the onboarding (flutter or cli) work. Application code can detect whether network is down if it wishes to. Re (2) : Something like this sounds reasonable. It may be better to attempt a PKAM auth and, if it actively fails (i.e. get the response code saying that pkam auth has failed), then do the stopping / unpairing / storage clearing / etc
@cconstab wdyt?
KISS for sure before we migrate functionality into the SDK..
This we can all do in client/application code for sure if we have 3
- We already have a way of checking if we are online or not
- If online do what we do
- If offline then get offline atClient
- Check if we got online via callback (we have that already too)
- Migrate to online or stay offline for mo
Having a way to get an atClient in local mode is the standalone need..
Pre-conditions to have atClient to work offline:
- Hive storage should have been initialized (Created in create() method of AtClientImpl - called by onBoard() method of AtClientService)
- AtClientManager should have been initialized with setCurrentAtSign
Expected behavior:
- SDK should give an instance of an atClient as long as the storage is fully initialized for an @sign
- If online works the way it is today
- else, all offline functions can be executed
Offline-supported operations matrix
Offline activity | Can work offline? |
---|---|
list keys | Yes |
list keys shared by other @sign (scan:other@sign) | No |
put private key | Yes |
put self key | Yes |
put public key | Yes |
put shared key with cached encryption public key of recipient | Yes |
put shared key | No |
get value for a key | Yes |
get value from other @sign | No |
notify | No |
sync | No |
Get a value from another atSign that has already been synch should be fine. Is that covered in get atKey?
Get a value from another atSign that has already been synch should be fine. Is that covered in get atKey?
@cconstab: The value of the key that belongs to another atSign can be fetched if there exists a cached key of the same in the current atSign.
Does this still need discussion or are we now in implementation?
Does this still need discussion or are we now in implementation?
@gkc: We have a version of the implementation checked-in into at_client_offline_access branch in at_client_sdk. Following is the link for the changes made. Pending work on this is to consume the changes into the apps and test them.
Progress made in PR 57
@sachins-geekyants has uptaken at_client offline mode changes into "wavi" app and changes are available in the following branch feat_onboard_offline.
@sachins-geekyants has reported two issues which are fixed and pushed to at_client_offline_access branch in at_client_sdk.
@sitaram-kalluri The approach as implemented right now in the PR is:
The current behaviour is, the app checks if the device is offline. If yes invokes
isAtClientReadyForOfflineAccess
which initializes theAtClient
and verifies if the encryption public key is available in the KeyStore.
This feels like a very clunky developer experience. We should require no changes to existing application code if at all possible, and I don't really see why it's necessary here. Application code should be able to construct their AtClient in the same way as now - the difference being, the AtClient will be constructed whether online or offline, as long as some preconditions are in place.
When a current user logs into an application, the "onboard" method is called in the "at_client_server.dart" file of the "at_client_mobile" module. Within the "onboard" method, the encryptionPublicKey is obtained from both the cloud and the local secondary in order to determine the "keyRestorePolicyStatus". However, if there is no network connection or the cloud secondary is unreachable while fetching the encryptionPublicKey, an exception is raised. This exception is not handled within the "onboard" method, resulting in its propagation to the mobile applications.
Proposed Solution:
- In order to enable offline access for the at_client, modify the "onboard" method as follows. When there is no network connection, the fetching of the encryptionPublicKey from the cloud server should be skipped or handle the exception. Instead, it should be checked if the encryptionPublicKey exists in the local storage. If the encryptionPublicKey is found in the local storage, allow the call to "AtClientManager.setCurrentAtSign" to operate in offline mode.
When an at_client is started in offline mode, there are certain operations that should not be permitted. These operations include the NotificationService, SyncService, and the creation/update of shared keys.
- Regarding the NotificationService and SyncService, we already have a mechanism in place to check for a network connection. If there is no network connection, the retry logic is triggered to initialize the NotificationService. This ensures that the NotificationService is only initialized when there is a network connection available. Similarly, in the sync serice, we skip the sync process if the network is not available.
- Regarding create/update of the shared key, When fetching encryptionPublicKey of the "sharedWith" atSign (if the cached copy of sharedWith atSign encryptionPublicKey is not available), an exception is raised to let user know on the failure.
Setting priority to P1
The changes are implemented and pushed to at_client_offline_access. Will pass the branch to @purnimavenkatasubbu for testing the changes.