Entities Protobuf – Service & Message Spec (v1alpha)

    This document describes the Entities gRPC API used to read, search, discover, and manage hypermedia entities (documents, groups, accounts, comments) and their change DAGs.

    Overview

      Entity: a content addressable object (document, group, account alias, comment) with a timeline of Change nodes forming a DAG.

      Timeline: per-entity DAG with roots, heads, and per-author “versions”.

      Discovery: best-effort background task that finds/syncs blobs for a target entity and optionally its children.

      Search: local fuzzy search over titles (default) and optionally bodies/comments.

    Protobuf Definition

      syntax = "proto3";
      
      package com.seed.entities.v1alpha;
      
      import "google/protobuf/timestamp.proto";
      
      import "google/protobuf/empty.proto";
      
      option go_package = "seed/backend/genproto/entities/v1alpha;entities";
      
      // Provides functionality to query information about Hypermedia Entities.
      service Entities {
        // Gets a change by ID.
        rpc GetChange(GetChangeRequest) returns (Change);
      
        // Gets the DAG of changes for an entity.
        rpc GetEntityTimeline(GetEntityTimelineRequest) returns (EntityTimeline);
      
        // Triggers a best-effort discovery of an entity.
        rpc DiscoverEntity(DiscoverEntityRequest) returns (DiscoverEntityResponse);
      
        // Finds the list of local entities whose titles match the input string.
        // A fuzzy search is performed among documents, groups and accounts.
        // For groups and documents, we match the title, while we match alias in accounts.
        rpc SearchEntities(SearchEntitiesRequest) returns (SearchEntitiesResponse);
      
        // Deletes an entity from the local node. It removes all the patches corresponding to it, including comments.
        rpc DeleteEntity(DeleteEntityRequest) returns (google.protobuf.Empty);
      
        // Lists deleted entities.
        rpc ListDeletedEntities(ListDeletedEntitiesRequest) returns (ListDeletedEntitiesResponse);
      
        // Undo the entity delition by removing the entity from the deleted list. That entity, if available
        // will be synced back in the next syncing round (or manually discovered).
        rpc UndeleteEntity(UndeleteEntityRequest) returns (google.protobuf.Empty);
      
        // List mentions of a given Entity across the locally-available content.
        rpc ListEntityMentions(ListEntityMentionsRequest) returns (ListEntityMentionsResponse);
      }
      
      // Request to get a change by ID.
      message GetChangeRequest {
        // ID of the change.
        string id = 1;
      }
      
      // Request to get the timeline of an entity.
      message GetEntityTimelineRequest {
        // The entity ID to get the timeline for.
        string id = 1;
      
        // Flag to include draft changes in the timeline,
        // otherwise they are omitted by default.
        bool include_drafts = 2;
      }
      
      // Request to discover an entity.
      message DiscoverEntityRequest {
        // Required. The account the entity belongs to.
        string account = 1;
      
        // Required. The path of the wanted entity.
        string path = 2;
      
        // Optional. Version of the entity to discover.
        string version = 3;
      
        // Optional. If true, we sync the document and the child
        // documents as well.
        bool recursive = 4;
      }
      
      // Describes the state of the discovery task.
      enum DiscoveryTaskState {
        // The task has just started.
        DISCOVERY_TASK_STARTED = 0;
      
        // The task is in progess — we keep looking for peers who can provide the content,
        // and downloading the content we are finding.
        DISCOVERY_TASK_IN_PROGRESS = 1;
      
        // The task has completed and the result is cached for the duration of the duration of the TTL.
        DISCOVERY_TASK_COMPLETED = 2;
      }
      
      // Response to discover an entity.
      message DiscoverEntityResponse {
        // The cached version of the document we've discovered within the last discovery process.
        string version = 1;
      
        // The state of the discovery task.
        DiscoveryTaskState state = 2;
      
        // The number of times we've called the discovery process for this entity and version so far.
        int32 call_count = 3;
      
        // The timestamp of the last result we've found.
        // It can be empty if the discovery is still in progress.
        google.protobuf.Timestamp last_result_time = 4;
      
        // The cached error message of the last discovery attempt if it failed.
        string last_error = 5;
      
        // The time when the currently cached result will expire, and a new discovery attempt will be made,
        // if the client keeps calling the discovery RPC.
        // Can be empty if no results have been found yet.
        google.protobuf.Timestamp result_expire_time = 6;
      
        // The progress of the discovery process.
        DiscoveryProgress progress = 7;
      }
      
      // Various metrics reporting on the progress of the discovery process.
      message DiscoveryProgress {
        // Number of peers we have found so far.
        int32 peers_found = 1;
      
        // Number of peers we have successfully synced with.
        int32 peers_synced_ok = 2;
      
        // Number of peers we have failed to sync with.
        int32 peers_failed = 3;
      
        // Number of blobs we have discovered so far.
        int32 blobs_discovered = 4;
      
        // Number of blobs we have successfully downloaded.
        int32 blobs_downloaded = 5;
      
        // Number of blobs we have failed to download.
        int32 blobs_failed = 6;
      }
      
      // A change to an entity.
      message Change {
        // ID of the change.
        string id = 1;
      
        // Author of the change.
        string author = 2;
      
        // Timestamp when the change was created.
        google.protobuf.Timestamp create_time = 3;
      
        // IDs of other changes this change depends on.
        repeated string deps = 4;
      
        // IDs of other changes that depend on this change.
        repeated string children = 6;
      
        // Indicates whether this changes comes from a trusted peer of ours.
        bool is_trusted = 5;
      
        // Indicates whether this change is a draft.
        bool is_draft = 7;
      }
      
      // The timeline of an entity.
      message EntityTimeline {
        // The ID of the entity.
        string id = 1;
      
        // Account ID of the owner of the entity.
        string owner = 2;
      
        // The set of changes for the entity keyed by change ID.
        map<string, Change> changes = 3;
      
        // The sorted list of change IDs by time.
        repeated string changes_by_time = 4;
      
        // The set of changes that has no dependencies.
        // Normally there should only be one root,
        // but just in case it's defined as a list.
        repeated string roots = 5;
      
        // The set of leaf changes considering the entire DAG.
        repeated string heads = 6;
      
        // The set of author versions/variants sorted by timestamp.
        repeated AuthorVersion author_versions = 7;
      }
      
      // Set of heads from a given author.
      message AuthorVersion {
        // Account ID of the author.
        string author = 1;
      
        // The set of leaf changes from that author.
        repeated string heads = 2;
      
        // The version string corresponding to the author's variant.
        // I.e. same as heads but concatenated with a '.' delimiter.
        string version = 3;
      
        // The timestamp of the author's version.
        // For compound versions the greatest timestamp is used.
        google.protobuf.Timestamp version_time = 4;
      }
      
      // An entity record found
      message Entity {
        // EID of the entity, including version, block id and range
        string id = 1;
      
        // Blob Id of the resource containing the matching record.
        string blob_id = 2;
      
        // The time of the version of the entity.
        google.protobuf.Timestamp version_time = 3;
      
        // In the case of comments, the document id
        // containing the comment.
        string doc_id = 4;
      
        // Content of the entity, depending on the type:
        // Alias in the case of account.
        // Title/Body in the case of groups and documents.
        // Body in the case of comments. We don't fill up the whole
        // block, just the part that contains the search term, with
        // the surrounding context. The context size is defined by
        // the context_size parameter.
        string content = 5;
      
        // The owner of the entity
        string owner = 6;
      
        // The type of the entity it coud be Title, Document, Comment, ...
        string type = 7;
      
        // Icon of the document containing that entity
        string icon = 8;
      
        // Parent document names
        repeated string parent_names = 9;
      
        // Metadata of the document containing that entity.
        string metadata = 10;
      }
      
      // Publication that has been deleted
      message DeletedEntity {
        // EID of the deleted entity.
        string id = 1;
      
        // When the entity was deleted.
        google.protobuf.Timestamp delete_time = 2;
      
        // Reason why this entity was deleted.
        string deleted_reason = 3;
      
        // Further metadata about the deleted entity, title, etc ...
        string metadata = 4;
      }
      // Request to
      message SearchEntitiesRequest {
        // Query to find. We Ssupport wildcards and phrases.
        // See https://sqlite.org/fts5.html#full_text_query_syntax.
        string query = 1;
      
        // Whether to look into all content available or just the titles.
        // If false, comments are not included in the search.
        // Default is false.
        bool include_body = 2;
      
        // Optional. The size of the text accompanying the search match.
        // Half of the size is before the match, and half after.
        // Default is 48 runes.
        int32 context_size = 3;
      
        // Optional. The account uid to filter the search by.
        // If not set, the search will be performed across all accounts.
        string account_uid = 4;
      
        // Optional. The account uid the user is logged in with.
        // This is used to filter out contacts that the user doesn't have access to.
        // If not set, we won't provide any contact entities in the response.
        string logged_account_uid = 5;
      }
      
      // A list of entities matching the request.
      message SearchEntitiesResponse {
        // Entities matching the input title
        repeated Entity entities = 1;
      
        // Token for the next page if there's any.
        string next_page_token = 2;
      }
      
      // Request for deleting an entity.
      message DeleteEntityRequest {
        // Entity ID of the entity to be removed.
        // All versions will also be removed.
        string id = 1;
      
        // Optional. Reason why the user wants to delete that entity.
        string reason = 2;
      }
      
      // Request for listing deleted entities.
      message ListDeletedEntitiesRequest {
        // Optional. Number of results per page. Default is defined by the server.
        int32 page_size = 1;
      
        // Optional. Value from next_page_token obtains from a previous response.
        string page_token = 2;
      }
      
      // Response with list of deleted entities.
      message ListDeletedEntitiesResponse {
        // List of deleted entities.
        repeated DeletedEntity deleted_entities = 1;
      
        // Token for the next page if there're more results.
        string next_page_token = 2;
      }
      
      // Request for restoring an entity.
      message UndeleteEntityRequest {
        // Entity ID of the entity to be restored.
        // All versions will also be restored.
        string id = 1;
      }
      
      // Request to list mentions of an entity.
      message ListEntityMentionsRequest {
        // Required. ID of the entity to list mentions for.
        string id = 1;
      
        // Optional. The size of the page to return by the server.
        // The server may ignore this, and return a bigger response.
        int32 page_size = 2;
      
        // Optional. The page token to continue the pagination.
        string page_token = 3;
      
        // Optional. Whether to return the results in descending order (newest-first).
        // By default mentions are listed in the chronological order,
        // according to the *locally perceived* order of the blobs that contain the mentions.
        //
        // I.e. we sort the links according to the time we receive the blobs, not according to the time blobs claim to have been created.
        // This is to prevent losing new mentions in case of receiving out-of-date blobs.
        //
        // This flag must remain the same when paginating through the results.
        bool reverse_order = 4;
      }
      
      // Response to list mentions of an entity.
      message ListEntityMentionsResponse {
        // Required. The list of mentions for the entity.
        repeated Mention mentions = 1;
      
        // Optional. Token for the next page if there's any.
        string next_page_token = 2;
      }
      
      // Mention of an Entity.
      // Source means the place where the mention was found.
      // Target means the entity being mentioned.
      message Mention {
        // Information about a structural blob that contains the mention.
        message BlobInfo {
          // The CID-formatted hash of the blob.
          string cid = 1;
      
          // The Account ID of the author of the blob.
          string author = 2;
      
          // The timestamp of the blob.
          google.protobuf.Timestamp create_time = 3;
        }
      
        // Required. The source blob where the mention was found.
        string source = 1;
      
        // Required. The Type of the source where the mention was found.
        string source_type = 2;
      
        // Required. Context can mean different things depending on the type of the source:
        // it can be the block ID when source type is a Document or Comment,
        // it can be a pretty-path when source type is a Group that mentions a Document.
        string source_context = 3;
      
        // Required. Information about the blob where the mention was found.
        BlobInfo source_blob = 4;
      
        // Required. Specifies whether the link points to the exact/pinned version of the target document,
        // or if the target version is a *suggested* minimum version, and a later one should be preferred if exists.
        bool is_exact_version = 5;
      
        // Optional. Specifies the document where the mention was found. Relevant for comments.
        string source_document = 6;
      
        // Optional. The version of the target Entity the link points to,
        // if one is specified in the link.
        string target_version = 7;
      
        // Optional. The fragment portion of the link.
        string target_fragment = 8;
      
        // Optional. The type of mention. Could be embed, link, ...
        string mention_type = 9;
      }