Daml contracts and visibility

I want to create data item contracts which one person creates and another agrees too. This seems simple enough, but I also want to either in that contract or another keep a list of the people who have seen the contract. Whats the simplest way to do this?

Hi @tonygair,

I’m not sure I get exactly what you mean by “people who have seen the contract”. Daml contracts are created with a complete list of parties that can see them (signatories + observers + choice controllers, usually called “stakeholders” as a whole). You cannot change that list without archiving the contract and creating a new one.

The system does not offer a way to track who among those “actually looked” at the contract, and similarly we cannot track whether any of those prints out the contract on paper and then shows it to someone else.

Could you perhaps try to clarify what you mean exactly by “have seen”?

apologies.
What I meant was that a document needs a request by a non signatory which is authorised by the owner who then makes them an observer for a limited amount of time.

I think perhaps my app should keep a secondary ledger recording the changes in observer?

You don’t need the other party’s authorization to make them an observer, and observer changes are part of the contract so go through the normal archive/recreate mechanism.

Here is a sketch of how that could work:

module Main where

import Daml.Script
import DA.List (delete)
import DA.Assert ((===))

template AgreementProposal
  with
    sender: Party
    recipient: Party
    extraInfo: Text
  where
    signatory sender
    observer recipient
    preconsuming choice AcceptProposal: ContractId Agreement
      controller recipient
      do
        create Agreement with temporaryAccess = [], ..

template Agreement
  with
    sender: Party
    recipient: Party
    extraInfo: Text
    temporaryAccess: [Party]
  where
    signatory sender, recipient
    observer temporaryAccess
    preconsuming choice GiveAccess: ContractId Agreement
      with viewer: Party
      controller recipient
      do
        create this with temporaryAccess = viewer :: temporaryAccess
    preconsuming choice RemoveAccess: ContractId Agreement
      with viewer: Party
      controller recipient
      do
        create this with temporaryAccess = delete viewer temporaryAccess

setup : Script ()
setup = script do
  alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")
  bob <- allocatePartyWithHint "Bob" (PartyIdHint "Bob")
  carol <- allocatePartyWithHint "Carol" (PartyIdHint "Carol")

  prop <- submit alice do
    createCmd AgreementProposal with
      sender = alice
      recipient = bob
      extraInfo = "Whatever"
  
  ag <- submit bob do
    exerciseCmd prop AcceptProposal
  
-- carol can't see the contract between bob and alice, as expected
  ags <- query @Agreement carol
  debug $ show ags
  length ags === 0

  ag <- submit bob do
    exerciseCmd ag GiveAccess with viewer = carol

  -- carol now has access
  ags <- query @Agreement carol
  debug $ show ags
  length ags === 1

  ag <- submit bob do
    exerciseCmd ag RemoveAccess with viewer = carol

  -- carol no longer has access
  ags <- query @Agreement carol
  debug $ show ags
  length ags === 0

Thanks Gary your response was detailed and extensive which I thank your for. Unfortunately I have had an eye operation and a gum infection/broken tooth which both led to me getting distracted so I apologise in now getting back to you sooner!
I plan for there to be many Alices and Bobs, but when permission is given, its given to see all contracts formed by Alice (Which Alice has flagged as visible. This permission is given with an access window. And if the option is taken this is recorded for the benefit of Alice.
This makes me think another table is needed, What do you think?

Hi @tonygair,

Really no worry on the delay. Hope you’re all right!

Daml does not really have a notion of “tagged as visible”. You can make a contract visible to a specific party by adding that party as an observer, and remove visibility by removing the observer. (That does mean, though, that you are creating a new contract and destroying it, as contracts are immutable.)

Depending on your system, you could have a very dynamic token generator that gives some temporary parties as readAs, but that’s a road I would not engage on lightly. The complexity can be quite high.

Without more details on your use-case, it’s going to be difficult to give you anything more precise.