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 rangestring 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 entitystring owner = 6;
// The type of the entity it coud be Title, Document, Comment, ...stringtype = 7;
// Icon of the document containing that entitystring 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;
}