Title: Artifact data scheme An artifact can be thought of as a source of knowledge. For example, if I am keeping notes on a research paper, the artifact is that paper. At a minimum, an artifact should have a standard header with metadata. It should store some authorship information (e.g. citation information). An artifact will have snapshots, which indicate current content either at a specific point in time or in a specific format. A website might have snapshots for different times it was scraped; a book might have snapshots for different editions of the book or for different formats (e.g. PDF and EPUB). ## The header This datatype will be common to all objects, including structures later in the knowledge graph itself. In many cases, such as a blob, the tags will be empty as they will be inherited implicitly through the parent Artifact type. ```go type Header struct { ID string Type ObjectType Created int64 Modified int64 Categories []string Tags []string Meta Metadata } ``` ## Metadata Metadata is a mapping of keys to values. These values might not be integers; consider the case where we'd want to track filesize or something like that. Metadata is defined as ```go type Value struct { Contents string Type string } type Metadata map[string]Value ``` ## Blobs With these two types defined, we can define a blob. A Blob has a header, a content type, and some data. ```go type Blob struct { ID string Format string // MIME type Body io.ReadCloser } ``` ## Citations A citation can be thought of as the bibliographic information for the artifact. Nothing in this should be strictly required. A citation occurs at the artifact level, but it could also occur at the snapshot level. This is like having base information (such as author and publisher) that applies to all of the snapshots, while the snapshot might override attributes like the specific edition. ### Publishers A starting point is the publisher type. ```go type Publisher struct { Header Header Name string Address string } ``` This is simple enough; the publisher really just needs a name and address, and it gets a Header whose Metadata can be used to inject any additional fields. ### Citations defined Putting some of these pieces together: ```go type Citation struct { Header Header DOI string Title string Year int Published time.Time Authors []string Publisher *Publisher Source string Abstract string } ``` We are strictly interested in containing the fields; the presentation layer can handle linking to the DOI, for example. ## Snapshots So we have the basic pieces in place now to define a snapshot: ```go type Snapshot struct { Header Header ArtifactID string Stored time.Time DateTime time.Time Citation *Citation Blobs map[MIME]*Blob } ``` It needs to know the ID of the artifact that it belongs to. We track the time it was stored --- which could be a unix timestamp, but for consistency with the other fields, we'll keep it as a standard time. DateTime is the time used for the snapshot; it can be a built off the year from the citation if needed, or it could be more refined. One design choice here that could be questioned is the used of the MIME type associated with the blob. The example I can think of here is the [[no-bs-guide-to-math-and-physics]], which has a pair of PDFs; one for reading on a tablet, and one for printing. I think that could be solved by using a [[MIME types|media type]] parameter like "application/pdf; format=screen". ## The artifact type Combining these together, we have the artifact type itself. ```go type Artifact struct { ID string Type ArtifactType Latest time.Time // latest snapshot History map[time.Time]*Snapshot } ``` The Type is an enumeration that can be added to; a few known types to start with are * Unknown * Custom * Article * Book * URL * Paper * Video * Image If the type is "Custom", the Header should have a metadata entry for "ArtifactType" to custom define it. The Latest should refer to the most Snapshot.DateTime in its collection of snapshots. ## Timestamps All timestamps should be suitable for referencing dates prior to epoch 0; they should be encoded in UTC and locally converted. For example, if the client is uploading a new artifact, it should convert its local time to UTC, then send this to the server. We can enforce this in Go using the `Local` timezone, but it's not foolproof. ## Next steps * Define protobufs. * Define a SQL schema.