# LinkedResources

The **linkedresources** module enables accounts to attach, update, and remove arbitrary binary data ("linked resources") to an on‑chain [Decentralised Identifier (DID)](https://www.w3.org/TR/did-core/) document. Each resource is versioned, signed by an authorised DID verification method, and subject to configurable size and length limits. In addition to resource management, the module provides parameter governance, rich gRPC/CLI queries, emitted events, a simulation framework, and CLI tooling.

***

## Contents

1. [Overview](#overview)
2. [Core Types](#core-types)
3. [Messages (Transactions)](#messages-transactions)
4. [Queries](#queries)
5. [Events](#events)
6. [Parameters](#parameters)
7. [Genesis](#genesis)
8. [CLI Commands](#cli-commands)
9. [Simulation](#simulation)
10. [Implementation Notes](#implementation-notes)

***

## Overview

The linkedresources module provides the following capabilities:

* **Create Linked Resource**: Attach a new binary payload to an existing DID. Each resource is uniquely identified by `(did, id)`, typed via a string (`type`), versioned (`version ≥ 1`), and cryptographically signed by a DID `capabilityInvocation` key.
* **Update Linked Resource**: Submit a new version of an existing resource. The `version` must increment by exactly 1, with a valid signature and respecting size/type limits. Only the latest version is stored on‑chain.
* **Delete Linked Resource**: Mark a resource as deleted. The on‑chain record remains for auditability; its `data` is zeroed, and its status changes to `DELETED`.
* **Parameter Governance**: Network governance (via a designated authority) can update module parameters that govern data size and identifier length limits.
* **Rich Queries**: gRPC and gRPC‑Gateway endpoints expose queries for parameters, single resources, all resources for a DID, or resources filtered by ID prefix.
* **Events**: Typed events are emitted for create, update, delete, and parameter updates.
* **CLI Tools**: `emped` commands for transactions and queries.
* **Simulation**: Weighted simulation operations for create, update, and delete flows.

***

## Core Types

### LinkedResource

```proto
message LinkedResource {
  string id = 1;      // Resource identifier
  string did = 2;     // Associated DID
  bytes  data = 3;    // Raw payload
  string type = 4;    // MIME‑like type string
  int64  version = 5; // Version number (≥1)
}
```

Represents the client‑facing payload and metadata for a linked resource.

### LinkedResourceEntity

```proto
message LinkedResourceEntity {
  bytes                     data = 1;
  string                   type = 2;
  int64                  version = 3;
  google.protobuf.Timestamp created_at = 4;
  google.protobuf.Timestamp updated_at = 5; // nullable
  LinkedResourceStatus       status = 6;
}
```

Internal storage format, capturing raw data, version, timestamps, and status (`ACTIVE` or `DELETED`).

### LinkedResourceRecord

```proto
message LinkedResourceRecord {
  LinkedResource             resource = 1;
  google.protobuf.Timestamp created_at = 2;
  google.protobuf.Timestamp updated_at = 3; // nullable
  LinkedResourceStatus       status = 4;
}
```

Returned by query endpoints, combining the core `LinkedResource` with its creation/update timestamps and status.

***

## Messages (Transactions)

All tx messages are defined under `empe.linkedresources.Msg`.

### CreateLinkedResource

```proto
rpc CreateLinkedResource(MsgCreateLinkedResource) returns (MsgCreateLinkedResourceResponse);

message MsgCreateLinkedResource {
  string    sender    = 1; // Bech32 address
  LinkedResource resource = 2;
  Signature signature = 3; // { method_id, sig_bytes }
}
```

* **Validation**: `sender` is valid, `resource.Validate()` passes (non‑empty fields, version ≥1, allowed characters), sizes within params, DID exists and is `ACTIVE`, signature authorised and valid, resource not already present.
* **Effects**: Charges `createLinkedResource_<tier>` fee, stores as `LinkedResourceEntity(status=ACTIVE)`, emits `EventCreateLinkedResource`.

### UpdateLinkedResource

```proto
rpc UpdateLinkedResource(MsgUpdateLinkedResource) returns (MsgUpdateLinkedResourceResponse);

message MsgUpdateLinkedResource {
  string    sender    = 1;
  LinkedResource resource = 2; // same id & did, version = previous+1
  Signature signature = 3;
}
```

* **Validation**: Same checks as create, plus existing resource must be `ACTIVE` and `resource.version = stored.version + 1`, signature valid.
* **Effects**: Charges `updateLinkedResource_<tier>` fee, updates `LinkedResourceEntity` (overwriting data, updating timestamps, keeping `status=ACTIVE`), emits `EventUpdateLinkedResource`.

### DeleteLinkedResource

```proto
rpc DeleteLinkedResource(MsgDeleteLinkedResource) returns (MsgDeleteLinkedResourceResponse);

message MsgDeleteLinkedResource {
  string                     sender  = 1;
  DeleteLinkedResourcePayload payload = 2; // { did, id, version }
  Signature                  signature = 3;
}

message DeleteLinkedResourcePayload {
  string did     = 1;
  string id      = 2;
  int64  version = 3; // must match current version
}
```

* **Validation**: Same identity checks, existing resource `ACTIVE`, `payload.version` matches stored version, signature valid.
* **Effects**: Charges `deleteLinkedResource_<tier>` fee, stores entity with zeroed `data`, `status=DELETED`, updated timestamp, emits `EventDeleteLinkedResource`.

### UpdateParams

```proto
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);

message MsgUpdateParams {
  string authority = 1; // must match configured authority
  Params params    = 2;
}
```

* **Validation**: `authority` matches module authority, `params.Validate()` passes (non‑zero limits).
* **Effects**: Persists new params, emits `EventUpdateParams`.

***

## Queries

All queries under `empe.linkedresources.Query`.

### Params

```proto
rpc Params(QueryParamsRequest) returns (QueryParamsResponse);
message QueryParamsResponse { Params params = 1; }
```

CLI: `emped query linkedresources params`

### LinkedResource

```proto
rpc LinkedResource(QueryLinkedResourceRequest) returns (QueryLinkedResourceResponse);
message QueryLinkedResourceResponse { LinkedResourceRecord linked_resource = 1; }
```

Fetch by DID and ID.

CLI: `emped query linkedresources resource <did> <id>`

### LinkedResources

```proto
rpc LinkedResources(QueryLinkedResourcesRequest) returns (QueryLinkedResourcesResponse);
message QueryLinkedResourcesResponse {
  repeated LinkedResourceRecord linked_resources = 1;
  cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
```

List all resources for a DID (paginated).

CLI: `emped query linkedresources resources <did> [--limit N --page P]`

### LinkedResourcesByPrefix

```proto
rpc LinkedResourcesByPrefix(QueryLinkedResourcesByPrefixRequest) returns (QueryLinkedResourcesByPrefixResponse);
```

Filter resources whose `id` starts with a given prefix. Supports pagination.

CLI: `emped query linkedresources resources <did> --prefix <prefix> [--limit N --page P]`

***

## Events

| Event                         | Attributes                                                                  |
| ----------------------------- | --------------------------------------------------------------------------- |
| **EventCreateLinkedResource** | `sender`, `did`, `resource_id`, `resource_type`, `resource_size`            |
| **EventUpdateLinkedResource** | `sender`, `did`, `resource_id`, `version`, `resource_type`, `resource_size` |
| **EventDeleteLinkedResource** | `sender`, `did`, `resource_id`                                              |
| **EventUpdateParams**         | `authority`, `params` (JSON‑encoded)                                        |

***

## Parameters

`Params` define module limits and defaults:

* `ResourceDataMaxSize` (int64): max bytes for `data` (default 64 KiB)
* `ResourceIdMaxLength` (int64): max characters for `id` (default 64)
* `ResourceTypeMaxLength` (int64): max characters for `type` (default 32)

Modifiable via the `MsgUpdateParams` transaction.

***

## Genesis

The `GenesisState` includes:

* `params`: initial `Params` values.
* `linked_resources`: a repeated list of `LinkedResourceRecord` entries (with resource payload, timestamps, and status).

On `InitGenesis`, all entries are loaded into state with `StoreLinkedResource`.

***

## CLI Commands

### Transaction Commands

```bash
emped tx linkedresources create-linked-resource <resource.json> <methodId> <sigBytes> --from <key>
emped tx linkedresources update-linked-resource <resource.json> <methodId> <sigBytes> --from <key>
emped tx linkedresources delete-linked-resource <did> <id> <version> <methodId> <sigBytes> --from <key>
```

### Query Commands

```bash
emped query linkedresources params
emped query linkedresources resource <did> <id>
emped query linkedresources resources <did> [--prefix <prefix>] [--limit N --page P]
```

***

## Simulation

Weighted operations registered for fuzz testing:

* `SimulateMsgCreateLinkedResource` (weight: 200)
* `SimulateMsgUpdateLinkedResource` (weight: 100)
* `SimulateMsgDeleteLinkedResource` (weight: 50)

These simulate DID document creation, resource operations, and fee handling.

***

## Implementation Notes

* **Storage Layout**: Keys stored as `<did>||0x00||<id>` under a module prefix for per‑DID iteration.
* **Internal Types**: `LinkedResourceEntity` for KV storage; `LinkedResourceRecord` for queries.
* **Fee Model**: Fees named `createLinkedResource_<tier>`, `updateLinkedResource_<tier>`, and `deleteLinkedResource_<tier>` based on DID tier.
* **DID Integration**: Signatures must be from a `capabilityInvocation` method in the DID document.
* **Validation**: Resources validated for format (`id/type` pattern) and size limits from `Params`.
* **Errors**: Defined errors include `ErrResourceTooLarge`, `ErrInvalidSignature`, `ErrLinkedResourceNotFound`, etc.
