Editing tasks: Clarifying what triggers the need for multi-sig

#1

I am working on a screen to edit task data and I am realizing I have some confusion about when multi-sig is required and when not.

I would image for most tasks there is a “draft” phase in which various aspects of the task are edited (e.g. brief, due date, manager, worker, payouts, etc). This is necessary because not all task data can be set with one transaction. It would make sense to me that in this phase that multisig would not be required. Is that correct?

Is there such a draft status? I see tasks only have statuses of ACTIVE, CANCELLED, or FINALIZED.

If status does not drive when multsig is required, what does?

I just created a task and assigned a due date and I see that it is in “ACTIVE” status. Does that task require multisig, even though other roles have not even been assigned and other data has not been set for the task?

Thanks for clarifying.

#2

There is currently no draft stage for a task on chain. This could be something we support in the future but it would be more cost effective to make changes to what will be on chain before it is on chain. If you plan to make revisions to a task before officially activating it (adding it to your colony on chain), it might be better to save a draft off chain and then add it on chain when you are ready.

We are doing something similar in the first version of the dApp. I think supporting drafts for tasks would be something we would want to support in our “extended protocol”, a JavaScript package that will make it easy for dApp developers to store and retrieve off chain data using IPFS with OrbitDB. We will start developing this after the first version of the dApp has launched.

All methods that modify a task use multisignature. In most cases, the MANAGER and WORKER need to sign the operation (only setTaskEvaluatorPayout and removeTaskEvaluatorRole require the MANAGER and EVALUATOR to sign). If you want to modify a task and there is no WORKER assigned, only the MANAGER will need to sign the operation. See here for more information.

In some ways, assigning the WORKER is like moving a task out of a “draft” stage. This might help frame things but this is not entirely accurate because the assigned WORKER can be unassigned, which would mean the task returns to the “draft” stage.

Each time you call a method that modifies a task (a method that requires multisignature) and requires the WORKER and MANAGER to sign the operation, and before a WORKER has been assigned, only the MANAGER needs to sign so the steps to modify the task would look like this:

const operation = await colonyClient.setTaskBrief.startOperation({
  taskId: 1,
  specificationHash: 'Qm...',
});

await operation.sign();
await operation.send();

I like to check if the connected wallet is one of the missing signees and sign the operation, then check if there are no missing signees and send the operation, which can be done right after the operation was started, therefore not requiring the operation to be stored and restored if the MANAGER is modifying the task and no WORKER has been assigned.

#3

Thanks for these details, Ryan. I still think a draft stage is a good idea, because otherwise adding a worker becomes like moving something from draft to active and its a “hidden” side effect in some ways. Might be better to make the move from draft to active explicit since it is such an important threshold: like signing a contract.

If it were possible to atomically (in one transaction) configure a task I might agree with having a task be active immediately after it is created, BUT creating and specing a task takes multiple transactions to set payouts, assign worker and evaluator, set due date, domain and skill, etc. To have each of these steps require multisig to be set even the first time seems onerous and cumbersome.

Imagine this scenario:

Two large entities are working on an important and large task in Colony.

Likely, lower level employees would be doing the initial drafting off chain, working out details.

Then once these lower level employees have agreed on the details, the task is put on chain and the different entities are assigned as worker, manager, evaluator, etc and the details of due dates, payouts, domain and skill, etc. are all set by one of the entities.

Then the entities move the review process up the chain of command where lawyers may be involved and things may need to be tweaked. Either party should be able to make such changes to the task, but not any other eth address. (single sig)

Once the lawyers have agreed, then the task goes to the CEOs for signature and ratification. It is only at that point that the task is really active. All parties should sign off to make the task active, just like signing any contract. (multisig)

After that, if any changes are needed, then it is like adding an addendum to a contract, in which case of course all parties would need to sign off on the addendum/changes. (multisig)

Viewed through this lens, draft becomes an important stage of the process and “active” takes on more meaning. (For example, what does it mean to have an “active” task when all of the require details like due date may not have been filled out? It is not semantically consistent.)

I think having a draft stage aligns more with how real world contracts work. Usually one party drafts it, other parties can make edits, and then it is signed and locked. After that addendums are needed to modifiy the contract and all parties need to sign those.

My 2 cents. Thanks for considering it.

1 Like
#4

Any thoughts on this, @ryanchristo?

#5

creating and specing a task takes multiple transactions to set payouts, assign worker and evaluator, set due date, domain and skill, etc

The specification, domain, skill, and due date can all be set at the time the task is added using addTask (no multisgnature required). All payouts can be set using setAllTaskPayouts (no multisgnature required) before the WORKER has been assigned or the EVALUTATOR has been reassigned (“reassigned” because the default is the same address as the MANAGER of the task, the address that sent the transaction).

Setting the WORKER and EVALUATOR will always require multisignature. It would be unfair to assign a task to someone without their approval because their reputation is at stake. For example, if they were assigned an impossible task, either outside of their skill set or with an unreasonable specification and due date, they would receive the lowest possible rating (1) and lose reputation.

I think part of the issue is that the documentation needs to make this more clear. This is my fault. There are really only two methods you need to call to set up a task: addTask and setAllTaskPayouts (no multisignature required). Then you will need to call setTaskWorkerRole to assign the worker with the worker’s approval (multisgnature required).

Any other changes to the task require multisignature because tasks on chain are ACTIVE. I like the idea of a draft stage but I think a draft is something that should not be on chain. A draft should be saved off chain to save transaction costs and modifying a task on chain should be a last resort and require the approval of all parties involved because their reputation is at stake.

In your example, if there is need for a review process where lawyers may be involved, I think the review process should take place before the task has been added on chain (activated). No matter what authority the reviewers may have off chain, they should not be able to modify any details of a task that would affect the parties involved who have their reputation at stake. This would fall outside the governance model that Colony is building and introduce ways for users to abuse their permissions.

Again, I think one of the main issues is that the documentation needs to be more clear about the process of adding a task on chain in a way that avoids too many steps (using the two methods before assigning a worker) and what it is at stake if task roles are assigned to an active task on chain (modification requires multisignature because reputation is at stake).

I hope that clarifies things a bit. Someone else from our team can chime in if they have anything to add but I think I hashed out some of the main reasons why the task structure is the way it is.

1 Like
#6

I created an issue in colonyJS to update the documentation:

#7

This idea has me thinking. If the draft was something that you wanted on chain, maybe you could create an extension contract that would allow users with certain permissions to add and edit a proposal (maybe users with the ADMINISTRATION role).

When the proposal is ready to become a task, you could call the task methods using a single method (one transaction) that uses the properties of the proposal to create a task. At which point the proposal would be finalized and the task would be activated. Thoughts?

1 Like
#8

Thanks, Ryan. I appreciate your thoughtful response, additional documentation, and suggestion for extension. That might work.

In general, I do think these kind of “helper” extension contracts that do a couple things at once for transaction efficiency and also to reduce the confusion and load on end users (e.g. why are so many transactions needed?) could be helpful. Such as:

  • create a task and set payouts with one transaction at once
  • create a colony, set a colony description hash, and set key administrative roles at once

For now I think it will work for me to use the existing process as you laid it out above, but I may choose to extend with a draft state some time in the future as a refinement.