desci-labs / desci-codex

Reference implementation of the CODEX protocol, using Ceramic and ComposeDB
8 stars 0 forks source link

Problems from mutability of streams #6

Closed m0ar closed 1 year ago

m0ar commented 1 year ago

The fact that streams are mutable is what makes Ceramic/ComposeDB a great fit for managing research objects. But for certain models, we do not want it. In this issue we discuss potential solutions.

DOD: we have a solution for working around mutability for certain type of objects.

m0ar commented 1 year ago

Reference initial commit instead of full state

Idea

Set the convention that for certain types of objects in the protocol, we look at the state of the stream at the first commit instead of at the tail. This would render the data immutable from the protocol perspective.

Critique

  1. The GraphQL endpoint for ComposeDB only supports latest state, so we'd need to query the HTTP API for these states. With a slim transformer, we can use the same types internally so it'd be a problem for the fetching code.
  2. The streams can still be mutated, so ComposeDB queries would show data not adhering to the spec.

Verdict

Possible. Not satisfactory because of the rift between spec and composeDB/graphql types.

m0ar commented 1 year ago

Read-only model fields

Idea

We/ceramic implements @readonly directives on model fields, disallowing updates to their content in the commit validation stage.

This could enable a model like this:

type Claim
  @createModel(accountRelation: LIST, description: "A reusable claim to be granted via attestation") 
{
  maintainer: DID! @documentAccount
  title: String! @readonly @string(maxLength: 100)
  description: @readonly String! @string(maxLength: 1000)
  badge: CID! @readonly
}

where the maintainer can create a reusable Claim, but not change the badge pic to a :hankey: when it's in wide use.

Equally important in attestations, where one shouldn't be able to switch the Claim from Great to Shitty at any point in time but should have the ability to revoke it:

type Attestation 
  @createModel(accountRelation: LIST, description: "General attestation")
{
  source: DID! @documentAccount
  targetID: StreamID! @readonly
  claimID: StreamID! @readonly @documentReference(model: "Claim")
  claim: Claim! @relationDocument(property: "claimID")
  revoked: Boolean!
}

Critique

  1. Initial reactions from the Ceramic are very positive, but you never know.
  2. Does not look to complicated so we could probably PR it to accelerate.

Verdict

Strongly preferable

m0ar commented 1 year ago

All thingID ref fields now have a thingVersion companion with the specific commit ref. This solves the theoretical issue, but in practice the indexing can be flaky, as an incoming @relationFrom edge can disappear if the latest version of the referrer has switched the streamID field. This is an indexing issue, not a fundamental modelling one. With accountRelation: SET it should be all good: https://github.com/orgs/ceramicstudio/projects/2