# Forward API Options
## Proposed Option
- pack(forward=True)
- unpack(unpack_wrapped_forward=True)
- parse_forward()
- build_forward()
```
# sender:
pack_res = pack(msg, to, forward=True)
print(pack_res.forwarded_msgs)
print(pack_res.packed_msg)
# mediator: no re-wrap
unpack_res = unpack(msg)
parse_forward(unpack_res.msg)
# mediator: re-wrap
unpack_res = unpack(msg)
forward_msg = parse_forward(unpack_res.msg)
new_forward = build_forward(forward_msg.plaintext_msg, to, enc_alg)
# reciever:
unpack_res = unpack(msg, unpack_wrapped_forward=True)
print(unpack_res.plaintext_msg)
print(unpack_res.forward_msg)
print(unpack_res.signed_msg)
print(unpack_res.metadata)
```
------------------don't look below--------------------------
## Options Overview
- Option 1: pack+forward; unpack+parse_forward
- Option 2: pack+forward; unpack or unpack_forward
- Option 3: pack(forward=True); unpack(unpack_wrapped_forward=True)
- Option 4: pack+forward; unpack(unpack_wrapped_forward=True)
**Proposed Option**: TBD
## Option 1: pack+forward; unpack+parse_forward
```
# sender
msg = pack(...)
forwarded_msg = forward(msg, to, enc_alg)
# mediator: no re-wrap
plaintext_unpack_result = unpack(msg)
msg = plaintext_unpack_result.plaintext_msg
if is_forward(msg):
forward_msg = parse_forward(msg)
print(forward_msg.payload)
# mediator: re-wrap
plaintext_unpack_result = unpack(msg)
msg = plaintext_unpack_result.plaintext_msg
if is_forward(msg):
forward_msg = parse_forward(msg)
new_forward_msg = forward(forward_msg, forward_msg.next, enc_alg)
print(new_forward_msg)
# reciever
plaintext_unpack_result = unpack(msg)
msg = plaintext_unpack_result.plaintext_msg
if is_forward(msg):
forward_msg = parse_forward(msg)
plaintext_unpack_result = unpack(forward_msg.payload)
msg = plaintext_unpack_result.plaintext_msg
```
## Option 2: pack+forward; unpack or unpack_forward
```
# sender
msg = pack(...)
forwarded_msg = forward(msg, to, enc_alg)
# mediator: no re-wrap
unpack_res = unpack_forward(msg)
print(unpack_res.forward_msg.payload)
# mediator: re-wrap
unpack_res = unpack_forward(msg)
new_forward = forward(unpack_res.forward_msg.plaintext_msg, to, enc_alg)
print(new_forward)
# reciever: Option 1: no Forward
unpack_res = unpack(msg)
msg = unpack_res.plaintext_msg
if is_forward(msg):
forward_msg = parse_forward(msg)
new_forward_msg = forward(forward_msg, forward_msg.next, enc_alg)
print(new_forward_msg)
# reciever: Option 2: with Forward
unpack_res = unpack_forward(msg)
print(unpack_res.plaintext_msg)
print(unpack_res.forward_msg)
print(unpack_res.signed_msg)
print(unpack_res.metadata)
```
## Option 3: pack(forward=True); build_forward; unpack(unpack_wrapped_forward=True)
```
# sender:
pack_res = pack(msg, to, forward=True)
print(pack_res.forwarded_msgs)
print(pack_res.packed_msg)
# mediator: no re-wrap
unpack_res = unpack(msg)
print(unpack_res.forward_msg.payload)
# mediator: re-wrap
unpack_res = unpack(msg)
new_forward = build_forward(unpack_res.forward_msg.plaintext_msg, to, enc_alg)
print(new_forward)
# reciever:
unpack_res = unpack(msg, unpack_wrapped_forward=True)
print(unpack_res.plaintext_msg)
print(unpack_res.forward_msg)
print(unpack_res.signed_msg)
print(unpack_res.metadata)
```
## Option 4: pack+forward; unpack(unpack_wrapped_forward=True)
```
# sender
msg = pack(...)
msg_to_bob = forward(msg, to, enc_alg)
# mediator: no re-wrap
unpack_res = unpack(msg)
print(unpack_res.forward_msg.payload)
# mediator: re-wrap
unpack_res = unpack(msg)
new_forward = forward(unpack_res.forward_msg.plaintext_msg, to, enc_alg)
print(new_forward)
# reciever
unpack_res = unpack(msg, process_re_wrapping=True)
print(unpack_res.plaintext_msg)
print(unpack_res.forward_msg)
print(unpack_res.signed_msg)
print(unpack_res.metadata)
```
## Details
#### Option 1: Forward on top of DID Comm pack/unpack: no re-wrap process
- Forward is implemeted in the separate package `/protocols/forward`
as essentially this is nothing but a protocol implemented on top of DID Comm.
- Reciever calls common `unpack`. There is also a helper method `parse_forward`.
- Sender should call `pack` and then optionally `forward`
Pros:
- Separate forward and core logic, as essentially Forward is not part of pack/unpack, but a protocol implemented on top of it
- Better from the single responsiblity principle
- Another approaches for routing may appear in future, as well as another versions of Forward protocol. Separating the API we can support such changes easily. If we embed forward into the pack/unpack API, then the core API may need to be changed if Forward is changed.
- Can support multiple version of the Forward protocol in future
- Helper methods make process of Forward on the reciever side easily
- The API is quite straighforward - no options for the user
Cons:
- There is a chance that in most of the cases a sender will have to call pack+forward all the time, so it will be kind of a boilerplate
- Due to possible re-wrapping, there is a chance that in most of the cases a receiver will have to call the reciever part of the code above in all the cases, so it will be kind of a boilerplate
- Welcomes creation of alternative Forward protocols which may be not what DID Comm spec wants
#### Option 2: Forward on top of DID Comm pack/unpack: re-wrap process
- Forward is implemeted in the separate package `/protocols/forward`
as essentially this is nothing but a protocol implemented on top of DID Comm.
- If Forward protocol is used/expected, sender and reciever can call `pack_forward` and `unpack_forward` instead of common `pack`/`unpack`.
Pros:
- Separate forward and core logic, as essentially Forward is not part of pack/unpack, but a protocol implemented on top of it
- Better from the single responsiblity principle
- Another approaches for routing may appear in future, as well as another versions of Forward protocol. Separating the API we can support such changes easily. If we embed forward into the pack/unpack API, then the core API may need to be changed if Forward is changed.
- Can support multiple version of the Forward protocol in future
- Helper methods make process of Forward on the reciever side easily
- No boilerplate code for the user
Cons:
- The API may be quite confusing - whether pack/unpack or pack_forward/unpack_forward needs to be called
- Welcomes creation of alternative Forward protocols which may be not what DID Comm spec wants
#### Option 3: Forward as part of DID Comm pack/unpack
- As Forward is part of DID Comm spec and most probably be used in most of the cases, Forward will be an optional part of DID Comm core (pack/unpack)
- Sender can optionally do forward to all recipients in the scope of `pack`
- Reciever can optionally process re-wrapping in the scope of `unpack`
Pros:
- Less options for the user and easier to understand the API (assuming that Forward is used in most of the cases)
- More compact calls for most of the cases (assuming that Forward is used in most of the cases)
- Doesn't welcome creation of alternative Forward protocols
Cons:
- Forward becomes part of core methods signature (arguments, return values). Potentially unused return parameters (forwarded_msgs, forward_unpack_result) if Forward is not used.
- Another approaches for routing may appear in future, as well as another versions of Forward protocol. The core API may have to be changed if Forward is changed.
- Not easily possible to support multiple version of the Forward protocol
#### Option 4: Forward on top of of DID Comm for sender and re-wrap process for reciever
- For the sender `forward` is a separate call to be called after `pack` (as in Option 1)
- For the reciver `forward` is optional part of `unpack` (as in Option 3)
Pros
- Less options for the reciever (assuming that Forward is used in most of the cases)
Cons:
- Another approaches for routing may appear in future, as well as another versions of Forward protocol. The core API may have to be changed if Forward is changed (`unpack` in particular)
- A bit inconsistent API (for the sender Forward is separate, while for reciver it's embedded)
- Not easily possible to support multiple versions of the Forward protocol