---
# System prepended metadata

title: ADR-003

---

---
title: ADR-003
id: adr-003
displayed_sidebar: resourcesSidebar
---

- **Author(s):** [Daniel Ribeiro](https://github.com/drgomesp)
- **Last Updated:** June 21, 2022
- **Status:** Draft
- **Deployment:** `integrate/adr-003`

# ADR-003: Buckets (Storage Classification)


## Summary
Associate data on the Sonr network together with the addition of a new resource type: buckets.


## Abstract
The canonical storage resource inside the Sonr network is the **Bucket** - an encrypted, schemaless, storage container.
By using buckets, developers may leverage a secure and private decentralized storage layer for their applications.


## Objectives
- Private and secure storage mechanism
- Support Access Control Lists
- Support CRUD operations for buckets and bucket content
- Support revokation of access


## Use Cases
- Store multiple associated files (application assets)
- Store staticly served files


## Concept
Conceptually, buckets behave similarly to a key-value store, where the keys are developer-created and mapped one-to-one with a CID.
The content is encrypted using the shared member's JWKs (JSON Web Keys).

Creating and managing buckets require updates to the underlying blockchain.
This includes deleting the bucket, adding new resources, or updating permissions.
The bucket model itself is stored in IPFS, but the CID for the model will be stored on-chain; this significantly reduces the usage of on-chain space.


## Bucket Model
The model for a bucket, which will be stored in IPFS, is as follows.

```go=
type Bucket struct {
    Did string
    Label string
    IsActive bool
    EncryptedJwks map[CID]map[PublicKey]EncryptedJWK
    Content map[string]CID
}

type CID string
type PublicKey string
type EncryptedJWK []byte
```

#### DID
A DID which uniquely identifies the bucket.

#### Label
A label for conveniently referencing the bucket.

#### IsActive
Reflects whether or not the bucket is active.
Inactive buckets cannot be modified.

#### EncryptedJwks
A map that stores the encrypted keys for each party who should have access to the content referenced by a CID.
Each CID entry contains a map of public keys (those of the members being granted access) to the JWK encrypted with that public key (PK). This allows the user to find the JWK they need to decrypt the data found with `CID`.

#### Content
Maps developer-defined keys to the CID for content. Content is posted via the APIs described below and can be found again via this map.


## Bucket API
At a high-level, the supported Bucket operations are:

### `CreateBucket(label)`
#### Parameters
`label (string)`
: The label for the bucket. A convenient way to reference the bucket in addition to the generated DID.

#### Description
Provisions a new bucket with the given label. New buckets will be initialized with a corresponding DID and DID Document. The `content` and `encryptedJwks` fields will be empty.

The bucket model itself will be persisted via IPFS, while the DID Document and a record which references the newly created bucket will be stored on-chain.

> Data persisted via IPFS will incur a storage cost relative to the size of the data storage. 
> Additonal costs will be incurred for storing the bucket reference on the chain.

### `UpdateLabel(did, new_label)`
#### Parameters
`did (string)`
: The DID of the bucket to update.

`new_label (string)`
: The new label for the bucket.

#### Description
Updates the label for the given bucket DID. Updating a label requires updating the bucket model in IPFS, which in turn will require an on-chain transaction to update the DID-CID pair.

> Data persisted to IPFS as part of an update will incur a storage cost that is linked to the size of the changed files. 
> IPFS will persist all files, so any files with changes will need to be re-uploaded, as well as the bucket model. 
> The changes will need to persist to the chain incurring an additional cost.

### `AddContent(did, name, encryptedContent, sharedMembersEncryptedKey)`
#### Parameters
`did (string)`
: The did of the bucket to add content to.

`name (string)`
: The key used to reference the content being added. This will be addressable via DID URL.

`encryptedContent (string)`
: The content to be added, encrypted with a JWK. The JWK should be one known only to the parties included in `sharedMembersEncryptedKeys`.

`sharedMembersEncryptedKeys (map[string]string)`
: A map containing the JWK used for encrypting the content, encrypted with the public key of each party to share with.

#### Description
Adds encrypted content to an existing bucket. 
A JWK is used to encrypt the content, and that JWK is encrypted once for every user who should have access to it. 
This enables data to be securely stored and access to be securely distributed.

> This call will require a new DID-CID pair to be added to the chain and as such will incur a cost.
> Additionally, this will charge for the cost of the file storage on IPFS

### `UpdateContent(did, name, encryptedContent, sharedMembersEncryptedKeys)`
#### Parameters
`did (string)`
: The did of the bucket to update content on.

`name (string)`
: The key used to reference the content being updated. The updated CID will replace the value found at this name.

`encryptedContent (string)`
: The new content, encrypted with a JWK. The JWK should be one known only to the parties included in `sharedMembersEncryptedKeys`.

`sharedMembersEncryptedKey (map[string]string)`
: A map containing the JWK used for encrypting the content, encrypted with the public key of each party to share with.

#### Description
Updates a bucket's content at the given name. The CID generated for the updated content will replace the CID found under `name` in the content map.
A new entry into the encrypted key map for `sharedMembersEncryptedKey`.

> This update will require a new DID-CID pair written to the chain.
> This change will charge for the size of the new entry on IPFS as well as CID on-chain update


### `RemoveContent(did, name)`
#### Parameters
`did (string)`
: The did of the bucket to update content on.

`name (string)`
: The content name.

#### Description
Removes content from a bucket.
This does not delete content from IPFS, but it removes the entry in the `content` map and `encryptedJwks` and map.

> Removing content, like updating, requires a single transaction on chain for updating the DID-CID pair for this bucket.

### `DeactivateBucket(did)`
#### Parameters
`did (string)`
: The bucket's DID.

#### Description
Sets the bucket's `IsActive` field to false. Requires a transaction on-chain to update the DID-CID pair.

### `GetBucket(did)`
#### Parameters
`did (string)`
: The bucket's DID.

#### Description
Returns the bucket model for the given DID. No transactions on-chain are required.

### `BucketExists(did)`
#### Parameters
`did (string)`
: The bucket's DID.

#### Description
Checks if a bucket exists for a given DID. No transactions on-chain are required.
