Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DocID json-schema definition #82

Open
PaulLeCam opened this issue Feb 15, 2021 · 14 comments
Open

DocID json-schema definition #82

PaulLeCam opened this issue Feb 15, 2021 · 14 comments

Comments

@PaulLeCam
Copy link
Contributor

PaulLeCam commented Feb 15, 2021

cip: 82
title: DocID json-schema definition
author: Paul Le Cam (@PaulLeCam)
status: Draft
category: Standards
type: RFC
created: 2021-02-15
edited: 2021-02-22

Simple Summary

Provide a static way to define a string in a JSON schema represents a Ceramic DocID, optionally with static references to the schema(s) that must be used by the referenced document.

Abstract

This CIP defines a standard way to add a reference to an existing Ceramic document in a JSON schema and references to existing JSON schemas, so it is possible to access this information about Ceramic documents at build time rather than only at runtime on created documents.

Motivation

It is sometimes necessary to reference Ceramic documents from other documents, such as a list containing the docIDs of individual Ceramic documents.
Currently, we are sometimes using definitions that can be referenced in a schema using "$ref": "#/definitions/CeramicDocId" for example, but this has not be defined as a standard.
Using local definitions to a schema also has the downside of providing no guaranty of being unique or having the definition matching any standard.

Furthermore, IDX definitions contain a schema property that references an existing schema, guarantying the IDX record associated to the definition matches this schema.
This CIP provides a way to implement similar logic for any schema independently of IDX.

Using this CIP, a NotesList schema could explicitly reference a Note schema with the following example:

{
  $schema: 'http://json-schema.org/draft-07/schema#',
  title: 'Notes',
  type: 'object',
  properties: {
    notes: {
      type: 'array',
      title: 'list',
      items: {
        type: 'object',
        title: 'item',
        properties: {
          note: { $ref: '#/definitions/NoteDocID' },
          title: {
            type: 'string',
            maxLength: 100,
          },
        },
        required: ['note'],
      },
    },
  },
  definitions: {
    NoteDocID: {
      type: 'string',
      $id: 'ceramic://doc',
      $ceramicSchema: '<Note schema docID>' ,
      maxLength: 150,
    },
  },
}

This way, by loading the Notes schema, it is possible by a tool/library to discover the Note schema the same way loading a IDX definition allows the discovery of the record's schema.

Specification

References to Ceramic schema should use a string with the $id field of ceramic://doc, and optionally with a $ceramicSchema property containing either a string or array of strings containing the DocID (implicit reference to latest version) or CommitID (specific version) of the supported schema(s):

{
  type: 'string',
  $id: 'ceramic://doc',
  $ceramicSchema: '<schema docID or commitID>' ,
  maxLength: 150,
}

Rationale

Using the $id field on the object gives a unique namespace (ceramic://) and identifier (doc) so it creates a convention that can be used in similar CIPs.

Having this static way of identifying if a document references another document allows to simplify the associated logic, rather than relying on checking all string fields for the ceramic:// prefix, or relying on "$ref": "#/definitions/CeramicDocId" matching the expected constraints.

This spec also allows to either define a single schema (using a string) or multiple ones (array of strings).
The use case would be to support different schemas for a single reference, for example a "media" schema could reference an "image" schema, but also the "audio" and "video" ones as acceptable document schemas: $ceramicSchema: ['<image schema docID>', '<audio schema docID>', '<video schema docID>'].

Backwards Compatibility

Ideally we should replace the use of the CeramicDocId definition in IDX schemas we provide, as well as examples and tutorials.

Implementation

None yet.

Security Considerations

None I'm aware of.

Copyright

Copyright and related rights waived via CC0.

@PaulLeCam PaulLeCam changed the title Ceramic Schema reference Ceramic Doc reference Feb 16, 2021
@oed
Copy link
Member

oed commented Feb 16, 2021

This seems pretty great!

A few questions:

Maybe naming the CIP DocID json-schema definition or something similar that inlcudes json-schmea would be more clear?

Why would we want to include multiple schemas in one reference? Would it not be better to have multiple definitions for each schema to decrease ambiguity?

I think the example would be more clear if you used a named definition!

@PaulLeCam PaulLeCam changed the title Ceramic Doc reference DocID json-schema definition Feb 16, 2021
@PaulLeCam
Copy link
Contributor Author

This seems pretty great!

Thanks!

Maybe naming the CIP DocID json-schema definition or something similar that inlcudes json-schmea would be more clear?

Yes good idea 👍

Why would we want to include multiple schemas in one reference? Would it not be better to have multiple definitions for each schema to decrease ambiguity?

At build time it's used to identify possible schemas the document could use, but it's not necessarily restricted to a single one.
For example we can have a media feed document that has items that can be of different types (image, audio or video) so at built time we can discover that we need to be aware of the image, audio and video schemas, but at runtime the loaded document will specify its schema anyways so we can have the runtime logic work accordingly.
The main use case here is similar to the GraphQL union type.

I think the example would be more clear if you used a named definition!

Sorry I'm not sure what you mean by named definition here?

@oed
Copy link
Member

oed commented Feb 16, 2021

Like so:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "IDXKeychain",
  "properties": {
    "notes": {
      "type": "array",
      "items": { "$ref": "#/definitions/DocID" }
    }
  },
  "additionalProperties": false,
  "required": [ "notes" ],
  "definitions": {
    "DocID": {
      "type": "string",
      "$id": "ceramic://doc",
      "$ceramicSchema": "<schema docID>",
      "maxLength": 150,
    }
  }
}

I think this makes it a bit clearer for someone who is trying to understand what this is :)

Also would be helpful to have an example with an actual Schema DocID!

@PaulLeCam
Copy link
Contributor Author

I don't think it makes much sense to use the definitions here because using $ceramicSchema makes the field specific to a given schema rather than generic to any document, so in this case this would be simpler:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "notes": {
      "type": "array",
      "items": {
        "type": "string",
        "$id": "ceramic://doc",
        "$ceramicSchema": "<schema docID>",
        "maxLength": 150
      }
    }
  },
  "additionalProperties": false,
  "required": ["notes"]
}

@oed
Copy link
Member

oed commented Feb 16, 2021

Yeah, that's simpler. I more meant that it would be easier to understand for someone reading this CIP because it clearly separates what is part of the DocID reference.

@PaulLeCam
Copy link
Contributor Author

I see, thanks! I updated the example.

@oed
Copy link
Member

oed commented Feb 16, 2021

'<Note schema docID>' should be '<Note schema commitID>' right?

@PaulLeCam
Copy link
Contributor Author

I should accept either, maybe we can name it docRef then as per Sergey's PR?

@oed
Copy link
Member

oed commented Feb 17, 2021

Schemas always have to be a CommitID afaik.

edit: disregard my misunderstanding :)

@oed
Copy link
Member

oed commented Feb 26, 2021

@PaulLeCam Any blockers for making a PR for this CIP?

@PaulLeCam
Copy link
Contributor Author

No blocker, I opened a PR for it that references this issue for discussions: #86

@oed
Copy link
Member

oed commented Feb 28, 2021

I'm seeing an issue if I have multiple docids in the same schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "ConvictionState",
  "properties": {
    "context": {
      "type": "string"
    },
    "supply": {
      "type": "number"
    },
    "participants": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/participants"
      }
    },
    "proposals": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/proposals"
      }
    }
  },
  "additionalProperties": false,
  "required": [
    "context",
    "supply",
    "participants",
    "proposals"
  ],
  "definitions": {
    "participants": {
      "type": "object",
      "properties": {
        "account": {
          "type": "string"
        },
        "balance": {
          "type": "number"
        },
        "convictions": {
          "type": "string",
          "$id": "ceramic://doc",
          "$ceramicSchema": "<Convictions commitid>",
          "maxLength": 150
        }
      },
      "required": [
        "account",
        "balance",
        "convictions"
      ]
    },
    "proposals": {
      "type": "object",
      "properties": {
        "proposal": {
          "type": "string",
          "$id": "ceramic://doc",
          "$ceramicSchema": "<Proposal docid>",
          "maxLength": 150
        },
        "totalConviction": {
          "type": "number"
        },
        "triggered": {
          "type": "boolean"
        }
      },
      "required": [
        "proposal",
        "totalConviction",
        "triggered"
      ]
    }
  }
}

At https://www.jsonschemavalidator.net/ I see this error:

image

@PaulLeCam
Copy link
Contributor Author

Seems like we can't use $id as I intended then, thanks for reporting this, I'll look for alternative options.

@PaulLeCam
Copy link
Contributor Author

@oed I created #88 and opened a PR to update CIP-82 with these changes in #89, I think that would nicely work around this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants