chore: import upstream snapshot with attribution
Backend Tests / Tests (other) (push) Failing after 1s
Backend Tests / Static Checks (push) Failing after 2s
Backend Tests / Tests (internal) (push) Failing after 2s
Backend Tests / Tests (server) (push) Failing after 1s
Backend Tests / Tests (store) (push) Failing after 1s
Build Canary Image / build-frontend (push) Failing after 1s
Frontend Tests / Lint (push) Failing after 1s
Build Canary Image / build-push (linux/amd64) (push) Has been skipped
Build Canary Image / build-push (linux/arm64) (push) Has been skipped
Build Canary Image / merge (push) Has been skipped
Frontend Tests / Build (push) Failing after 1s
Release Please / release-please (push) Failing after 0s
Proto Linter / Lint Protos (push) Failing after 2s

This commit is contained in:
wehub-resource-sync
2026-07-13 12:02:24 +08:00
commit 4cddfcf2f3
1040 changed files with 200957 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
# Memos API Design
This API design should follow the guidelines and best practices outlined in the [Google API Improvement Proposals (AIPs)](https://google.aip.dev/).
+46
View File
@@ -0,0 +1,46 @@
syntax = "proto3";
package memos.api.v1;
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
option go_package = "gen/api/v1";
service AIService {
// Transcribe transcribes an audio file using an instance AI provider.
rpc Transcribe(TranscribeRequest) returns (TranscribeResponse) {
option (google.api.http) = {
post: "/api/v1/ai:transcribe"
body: "*"
};
option (google.api.method_signature) = "audio";
}
}
message TranscribeRequest {
// Required. Audio input.
TranscriptionAudio audio = 1 [(google.api.field_behavior) = REQUIRED];
}
message TranscriptionAudio {
oneof source {
// Inline audio bytes.
bytes content = 1 [(google.api.field_behavior) = INPUT_ONLY];
// URI for audio content. Reserved for future use.
string uri = 2;
}
// Optional. The uploaded filename.
string filename = 3 [(google.api.field_behavior) = OPTIONAL];
// Optional. The MIME type of the input audio.
string content_type = 4 [(google.api.field_behavior) = OPTIONAL];
}
message TranscribeResponse {
// The transcribed text.
string text = 1;
}
+182
View File
@@ -0,0 +1,182 @@
syntax = "proto3";
package memos.api.v1;
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
option go_package = "gen/api/v1";
service AttachmentService {
// CreateAttachment creates a new attachment.
rpc CreateAttachment(CreateAttachmentRequest) returns (Attachment) {
option (google.api.http) = {
post: "/api/v1/attachments"
body: "attachment"
};
option (google.api.method_signature) = "attachment";
}
// ListAttachments lists all attachments.
rpc ListAttachments(ListAttachmentsRequest) returns (ListAttachmentsResponse) {
option (google.api.http) = {get: "/api/v1/attachments"};
}
// GetAttachment returns an attachment by name.
rpc GetAttachment(GetAttachmentRequest) returns (Attachment) {
option (google.api.http) = {get: "/api/v1/{name=attachments/*}"};
option (google.api.method_signature) = "name";
}
// UpdateAttachment updates an attachment.
rpc UpdateAttachment(UpdateAttachmentRequest) returns (Attachment) {
option (google.api.http) = {
patch: "/api/v1/{attachment.name=attachments/*}"
body: "attachment"
};
option (google.api.method_signature) = "attachment,update_mask";
}
// DeleteAttachment deletes an attachment by name.
rpc DeleteAttachment(DeleteAttachmentRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=attachments/*}"};
option (google.api.method_signature) = "name";
}
// BatchDeleteAttachments deletes multiple attachments in one request.
rpc BatchDeleteAttachments(BatchDeleteAttachmentsRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
post: "/api/v1/attachments:batchDelete"
body: "*"
};
}
}
enum MotionMediaFamily {
MOTION_MEDIA_FAMILY_UNSPECIFIED = 0;
APPLE_LIVE_PHOTO = 1;
ANDROID_MOTION_PHOTO = 2;
}
enum MotionMediaRole {
MOTION_MEDIA_ROLE_UNSPECIFIED = 0;
STILL = 1;
VIDEO = 2;
CONTAINER = 3;
}
message MotionMedia {
MotionMediaFamily family = 1;
MotionMediaRole role = 2;
string group_id = 3;
int64 presentation_timestamp_us = 4;
bool has_embedded_video = 5;
}
message Attachment {
option (google.api.resource) = {
type: "memos.api.v1/Attachment"
pattern: "attachments/{attachment}"
singular: "attachment"
plural: "attachments"
};
// The name of the attachment.
// Format: attachments/{attachment}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// Output only. The creation timestamp.
google.protobuf.Timestamp create_time = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
// The filename of the attachment.
string filename = 3 [(google.api.field_behavior) = REQUIRED];
// Input only. The content of the attachment.
bytes content = 4 [(google.api.field_behavior) = INPUT_ONLY];
// Optional. The external link of the attachment.
string external_link = 5 [(google.api.field_behavior) = OPTIONAL];
// The MIME type of the attachment.
string type = 6 [(google.api.field_behavior) = REQUIRED];
// Output only. The size of the attachment in bytes.
int64 size = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
// Optional. The related memo. Refer to `Memo.name`.
// Format: memos/{memo}
optional string memo = 8 [(google.api.field_behavior) = OPTIONAL];
// Optional. Motion media metadata.
MotionMedia motion_media = 9 [(google.api.field_behavior) = OPTIONAL];
}
message CreateAttachmentRequest {
// Required. The attachment to create.
Attachment attachment = 1 [(google.api.field_behavior) = REQUIRED];
// Optional. The attachment ID to use for this attachment.
// If empty, a unique ID will be generated.
string attachment_id = 2 [(google.api.field_behavior) = OPTIONAL];
}
message ListAttachmentsRequest {
// Optional. The maximum number of attachments to return.
// The service may return fewer than this value.
// If unspecified, at most 50 attachments will be returned.
// The maximum value is 1000; values above 1000 will be coerced to 1000.
int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token, received from a previous `ListAttachments` call.
// Provide this to retrieve the subsequent page.
string page_token = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. Filter to apply to the list results.
// Example: "mime_type==\"image/png\"" or "filename.contains(\"test\")"
// Supported operators: =, !=, <, <=, >, >=, : (contains), in
// Supported fields: filename, mime_type, create_time, memo
string filter = 3 [(google.api.field_behavior) = OPTIONAL];
// Optional. The order to sort results by.
// Example: "create_time desc" or "filename asc"
string order_by = 4 [(google.api.field_behavior) = OPTIONAL];
}
message ListAttachmentsResponse {
// The list of attachments.
repeated Attachment attachments = 1;
// A token that can be sent as `page_token` to retrieve the next page.
// If this field is omitted, there are no subsequent pages.
string next_page_token = 2;
}
message GetAttachmentRequest {
// Required. The attachment name of the attachment to retrieve.
// Format: attachments/{attachment}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Attachment"}
];
}
message UpdateAttachmentRequest {
// Required. The attachment which replaces the attachment on the server.
Attachment attachment = 1 [(google.api.field_behavior) = REQUIRED];
// Required. The list of fields to update.
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
}
message DeleteAttachmentRequest {
// Required. The attachment name of the attachment to delete.
// Format: attachments/{attachment}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Attachment"}
];
}
message BatchDeleteAttachmentsRequest {
repeated string names = 1 [(google.api.field_behavior) = REQUIRED];
}
+115
View File
@@ -0,0 +1,115 @@
syntax = "proto3";
package memos.api.v1;
import "api/v1/user_service.proto";
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
option go_package = "gen/api/v1";
service AuthService {
// GetCurrentUser returns the authenticated user's information.
// Validates the access token and returns user details.
// Similar to OIDC's /userinfo endpoint.
rpc GetCurrentUser(GetCurrentUserRequest) returns (GetCurrentUserResponse) {
option (google.api.http) = {get: "/api/v1/auth/me"};
}
// SignIn authenticates a user with credentials and returns tokens.
// On success, returns an access token and sets a refresh token cookie.
// Supports password-based and SSO authentication methods.
rpc SignIn(SignInRequest) returns (SignInResponse) {
option (google.api.http) = {
post: "/api/v1/auth/signin"
body: "*"
};
}
// SignOut terminates the user's authentication.
// Revokes the refresh token and clears the authentication cookie.
rpc SignOut(SignOutRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {post: "/api/v1/auth/signout"};
}
// RefreshToken exchanges a valid refresh token for a new access token.
// The refresh token is read from the HttpOnly cookie.
// Returns a new short-lived access token.
rpc RefreshToken(RefreshTokenRequest) returns (RefreshTokenResponse) {
option (google.api.http) = {
post: "/api/v1/auth/refresh"
body: "*"
};
}
}
message GetCurrentUserRequest {}
message GetCurrentUserResponse {
// The authenticated user's information.
User user = 1;
}
message SignInRequest {
// Nested message for password-based authentication credentials.
message PasswordCredentials {
// The username to sign in with.
string username = 1 [(google.api.field_behavior) = REQUIRED];
// The password to sign in with.
string password = 2 [(google.api.field_behavior) = REQUIRED];
}
// Nested message for SSO authentication credentials.
message SSOCredentials {
// The resource name of the SSO provider.
// Format: identity-providers/{uid}
string idp_name = 1 [(google.api.field_behavior) = REQUIRED];
// The authorization code from the SSO provider.
string code = 2 [(google.api.field_behavior) = REQUIRED];
// The redirect URI used in the SSO flow.
string redirect_uri = 3 [(google.api.field_behavior) = REQUIRED];
// The PKCE code verifier for enhanced security (RFC 7636).
// Optional - enables PKCE flow protection against authorization code interception.
string code_verifier = 4 [(google.api.field_behavior) = OPTIONAL];
}
// Authentication credentials. Provide one method.
oneof credentials {
// Username and password authentication.
PasswordCredentials password_credentials = 1;
// SSO provider authentication.
SSOCredentials sso_credentials = 2;
}
}
message SignInResponse {
// The authenticated user's information.
User user = 1;
// The short-lived access token for API requests.
// Store in memory only, not in localStorage.
string access_token = 2;
// When the access token expires.
// Client should call RefreshToken before this time.
google.protobuf.Timestamp access_token_expires_at = 3;
}
message SignOutRequest {}
message RefreshTokenRequest {}
message RefreshTokenResponse {
// The new short-lived access token.
string access_token = 1;
// When the access token expires.
google.protobuf.Timestamp expires_at = 2;
}
+23
View File
@@ -0,0 +1,23 @@
syntax = "proto3";
package memos.api.v1;
option go_package = "gen/api/v1";
enum State {
STATE_UNSPECIFIED = 0;
NORMAL = 1;
ARCHIVED = 2;
}
// Used internally for obfuscating the page token.
message PageToken {
int32 limit = 1;
int32 offset = 2;
}
enum Direction {
DIRECTION_UNSPECIFIED = 0;
ASC = 1;
DESC = 2;
}
+147
View File
@@ -0,0 +1,147 @@
syntax = "proto3";
package memos.api.v1;
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
option go_package = "gen/api/v1";
service IdentityProviderService {
// ListIdentityProviders lists identity providers.
rpc ListIdentityProviders(ListIdentityProvidersRequest) returns (ListIdentityProvidersResponse) {
option (google.api.http) = {get: "/api/v1/identity-providers"};
}
// GetIdentityProvider gets an identity provider.
rpc GetIdentityProvider(GetIdentityProviderRequest) returns (IdentityProvider) {
option (google.api.http) = {get: "/api/v1/{name=identity-providers/*}"};
option (google.api.method_signature) = "name";
}
// CreateIdentityProvider creates an identity provider.
rpc CreateIdentityProvider(CreateIdentityProviderRequest) returns (IdentityProvider) {
option (google.api.http) = {
post: "/api/v1/identity-providers"
body: "identity_provider"
};
option (google.api.method_signature) = "identity_provider";
}
// UpdateIdentityProvider updates an identity provider.
rpc UpdateIdentityProvider(UpdateIdentityProviderRequest) returns (IdentityProvider) {
option (google.api.http) = {
patch: "/api/v1/{identity_provider.name=identity-providers/*}"
body: "identity_provider"
};
option (google.api.method_signature) = "identity_provider,update_mask";
}
// DeleteIdentityProvider deletes an identity provider.
rpc DeleteIdentityProvider(DeleteIdentityProviderRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=identity-providers/*}"};
option (google.api.method_signature) = "name";
}
}
message IdentityProvider {
option (google.api.resource) = {
type: "memos.api.v1/IdentityProvider"
pattern: "identity-providers/{idp}"
name_field: "name"
singular: "identityProvider"
plural: "identityProviders"
};
// The resource name of the identity provider.
// Format: identity-providers/{idp}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// Required. The type of the identity provider.
Type type = 2 [(google.api.field_behavior) = REQUIRED];
// Required. The display title of the identity provider.
string title = 3 [(google.api.field_behavior) = REQUIRED];
// Optional. Filter applied to user identifiers.
string identifier_filter = 4 [(google.api.field_behavior) = OPTIONAL];
// Required. Configuration for the identity provider.
IdentityProviderConfig config = 5 [(google.api.field_behavior) = REQUIRED];
enum Type {
TYPE_UNSPECIFIED = 0;
// OAuth2 identity provider.
OAUTH2 = 1;
}
}
message IdentityProviderConfig {
oneof config {
OAuth2Config oauth2_config = 1;
}
}
message FieldMapping {
string identifier = 1;
string display_name = 2;
string email = 3;
string avatar_url = 4;
}
message OAuth2Config {
string client_id = 1;
string client_secret = 2;
string auth_url = 3;
string token_url = 4;
string user_info_url = 5;
repeated string scopes = 6;
FieldMapping field_mapping = 7;
}
message ListIdentityProvidersRequest {}
message ListIdentityProvidersResponse {
// The list of identity providers.
repeated IdentityProvider identity_providers = 1;
}
message GetIdentityProviderRequest {
// Required. The resource name of the identity provider to get.
// Format: identity-providers/{idp}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/IdentityProvider"}
];
}
message CreateIdentityProviderRequest {
// Required. The identity provider to create.
IdentityProvider identity_provider = 1 [(google.api.field_behavior) = REQUIRED];
// Optional. The ID to use for the identity provider, which will become the final component of the resource name.
// If not provided, the system will generate one.
string identity_provider_id = 2 [(google.api.field_behavior) = OPTIONAL];
}
message UpdateIdentityProviderRequest {
// Required. The identity provider to update.
IdentityProvider identity_provider = 1 [(google.api.field_behavior) = REQUIRED];
// Required. The update mask applies to the resource. Only the top level fields of
// IdentityProvider are supported.
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
}
message DeleteIdentityProviderRequest {
// Required. The resource name of the identity provider to delete.
// Format: identity-providers/{idp}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/IdentityProvider"}
];
}
+360
View File
@@ -0,0 +1,360 @@
syntax = "proto3";
package memos.api.v1;
import "api/v1/user_service.proto";
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "google/type/color.proto";
option go_package = "gen/api/v1";
service InstanceService {
// Gets the instance profile.
rpc GetInstanceProfile(GetInstanceProfileRequest) returns (InstanceProfile) {
option (google.api.http) = {get: "/api/v1/instance/profile"};
}
// Gets an instance setting.
rpc GetInstanceSetting(GetInstanceSettingRequest) returns (InstanceSetting) {
option (google.api.http) = {get: "/api/v1/{name=instance/settings/*}"};
option (google.api.method_signature) = "name";
}
// Batch gets instance settings.
rpc BatchGetInstanceSettings(BatchGetInstanceSettingsRequest) returns (BatchGetInstanceSettingsResponse) {
option (google.api.http) = {
post: "/api/v1/instance/settings:batchGet"
body: "*"
};
}
// Updates an instance setting.
rpc UpdateInstanceSetting(UpdateInstanceSettingRequest) returns (InstanceSetting) {
option (google.api.http) = {
patch: "/api/v1/{setting.name=instance/settings/*}"
body: "setting"
};
option (google.api.method_signature) = "setting,update_mask";
}
// Tests notification email delivery with the provided or stored SMTP settings.
rpc TestInstanceEmailSetting(TestInstanceEmailSettingRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
post: "/api/v1/instance/settings/notification:testEmail"
body: "*"
};
}
// GetInstanceStats returns resource usage statistics for the instance. Admin only.
rpc GetInstanceStats(GetInstanceStatsRequest) returns (InstanceStats) {
option (google.api.http) = {get: "/api/v1/instance/stats"};
}
}
// Instance profile message containing basic instance information.
message InstanceProfile {
// Version is the current version of instance.
string version = 2;
// Demo indicates if the instance is in demo mode.
bool demo = 3;
// Instance URL is the URL of the instance.
string instance_url = 6;
// The first administrator who set up this instance, for display purposes.
// May be null on an instance that has lost all admins; use needs_setup to
// determine whether initial setup is actually required.
User admin = 7;
// Commit is the current build commit of instance.
string commit = 8;
// NeedsSetup is true when the instance has no users yet and requires initial
// setup (creating the first admin account). Unlike a null admin, this stays
// false once any user exists, so an instance that has lost its admins is not
// mistaken for a fresh install.
bool needs_setup = 9;
}
// Request for instance profile.
message GetInstanceProfileRequest {}
// An instance setting resource.
message InstanceSetting {
option (google.api.resource) = {
type: "memos.api.v1/InstanceSetting"
pattern: "instance/settings/{setting}"
singular: "instanceSetting"
plural: "instanceSettings"
};
// The name of the instance setting.
// Format: instance/settings/{setting}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
oneof value {
GeneralSetting general_setting = 2;
StorageSetting storage_setting = 3;
MemoRelatedSetting memo_related_setting = 4;
TagsSetting tags_setting = 5;
NotificationSetting notification_setting = 6;
AISetting ai_setting = 7;
}
// Enumeration of instance setting keys.
enum Key {
KEY_UNSPECIFIED = 0;
// GENERAL is the key for general settings.
GENERAL = 1;
// STORAGE is the key for storage settings.
STORAGE = 2;
// MEMO_RELATED is the key for memo related settings.
MEMO_RELATED = 3;
// TAGS is the key for tag metadata.
TAGS = 4;
// NOTIFICATION is the key for notification transport settings.
NOTIFICATION = 5;
// AI is the key for AI provider settings.
AI = 6;
}
// General instance settings configuration.
message GeneralSetting {
// disallow_user_registration disallows user registration.
bool disallow_user_registration = 2;
// disallow_password_auth disallows password authentication.
bool disallow_password_auth = 3;
// additional_script is the additional script.
string additional_script = 4;
// additional_style is the additional style.
string additional_style = 5;
// custom_profile is the custom profile.
CustomProfile custom_profile = 6;
// week_start_day_offset is the week start day offset from Sunday.
// 0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, 4: Thursday, 5: Friday, 6: Saturday
// Default is Sunday.
int32 week_start_day_offset = 7;
// disallow_change_username disallows changing username.
bool disallow_change_username = 8;
// disallow_change_nickname disallows changing nickname.
bool disallow_change_nickname = 9;
// Custom profile configuration for instance branding.
message CustomProfile {
string title = 1;
string description = 2;
string logo_url = 3;
}
}
// Storage configuration settings for instance attachments.
message StorageSetting {
// Storage type enumeration for different storage backends.
enum StorageType {
STORAGE_TYPE_UNSPECIFIED = 0;
// DATABASE is the database storage type.
DATABASE = 1;
// LOCAL is the local storage type.
LOCAL = 2;
// S3 is the S3 storage type.
S3 = 3;
}
// storage_type is the storage type.
StorageType storage_type = 1;
// The template of file path.
// e.g. assets/{timestamp}_{filename}
string filepath_template = 2;
// The max upload size in megabytes.
int64 upload_size_limit_mb = 3;
// S3 configuration for cloud storage backend.
// Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-go/
message S3Config {
string access_key_id = 1;
string access_key_secret = 2 [(google.api.field_behavior) = INPUT_ONLY];
string endpoint = 3;
string region = 4;
string bucket = 5;
bool use_path_style = 6;
// insecure_skip_tls_verify disables TLS certificate verification when connecting
// to the S3 endpoint. Only enable this for trusted endpoints that use a self-signed
// certificate; it removes protection against man-in-the-middle attacks.
bool insecure_skip_tls_verify = 7;
}
// The S3 config.
S3Config s3_config = 4;
}
// Memo-related instance settings and policies.
message MemoRelatedSetting {
reserved 2;
reserved "display_with_update_time";
// content_length_limit is the limit of content length. Unit is byte.
int32 content_length_limit = 3;
// enable_double_click_edit enables editing on double click.
bool enable_double_click_edit = 4;
// reactions is the list of reactions.
repeated string reactions = 7;
}
// Metadata for a tag.
message TagMetadata {
// Optional background color for the tag label.
// When unset, the default tag color is used.
google.type.Color background_color = 1;
// Whether memos with this tag should have their content blurred.
bool blur_content = 2;
}
// Tag metadata configuration.
// Active tag metadata is stored in per-user tag settings.
// This message remains for backward compatibility with existing clients and migrations.
message TagsSetting {
// Map of tag name pattern to tag metadata.
// Each key is treated as an anchored regular expression (^pattern$),
// so a single entry like "project/.*" matches all tags under that prefix.
// Exact tag names are also valid (they are trivially valid regex patterns).
map<string, TagMetadata> tags = 1;
}
// Notification transport configuration.
message NotificationSetting {
EmailSetting email = 1;
// Email delivery configuration for notifications.
message EmailSetting {
bool enabled = 1;
string smtp_host = 2;
int32 smtp_port = 3;
string smtp_username = 4;
string smtp_password = 5 [(google.api.field_behavior) = INPUT_ONLY];
string from_email = 6;
string from_name = 7;
string reply_to = 8;
bool use_tls = 9;
bool use_ssl = 10;
}
}
// AI provider configuration settings.
message AISetting {
// providers is the list of AI provider configurations available instance-wide.
repeated AIProviderConfig providers = 1;
// transcription is the speech-to-text feature configuration.
// When unset or transcription.provider_id is empty, transcription is disabled.
TranscriptionConfig transcription = 2;
}
// AIProviderConfig represents one callable AI provider connection.
message AIProviderConfig {
string id = 1;
string title = 2;
AIProviderType type = 3;
string endpoint = 4;
// api_key is write-only and is never returned by GetInstanceSetting.
string api_key = 5 [(google.api.field_behavior) = INPUT_ONLY];
// api_key_set indicates whether an API key is stored for this provider.
bool api_key_set = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
// api_key_hint is a masked hint for the stored API key.
string api_key_hint = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
}
// AIProviderType is the provider implementation type.
enum AIProviderType {
AI_PROVIDER_TYPE_UNSPECIFIED = 0;
OPENAI = 1;
GEMINI = 2;
}
// TranscriptionConfig configures the speech-to-text feature.
message TranscriptionConfig {
// provider_id references an entry in AISetting.providers[].id.
// Empty string means transcription is disabled.
string provider_id = 1;
// model is the provider-specific model identifier.
// Empty string falls back to the engine default
// (whisper-1 for OPENAI providers, gemini-2.5-flash for GEMINI providers).
string model = 2;
// language is the default ISO 639-1 language hint sent to the provider.
// Empty string lets the provider auto-detect.
string language = 3;
// prompt is a default spelling/vocabulary hint passed to the provider.
string prompt = 4;
}
}
// Request message for GetInstanceSetting method.
message GetInstanceSettingRequest {
// The resource name of the instance setting.
// Format: instance/settings/{setting}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/InstanceSetting"}
];
}
// Request message for BatchGetInstanceSettings method.
message BatchGetInstanceSettingsRequest {
// The resource names of the instance settings.
// Format: instance/settings/{setting}
repeated string names = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/InstanceSetting"}
];
}
// Response message for BatchGetInstanceSettings method.
message BatchGetInstanceSettingsResponse {
// The instance settings in the same order as the input names.
repeated InstanceSetting settings = 1;
}
// Request message for UpdateInstanceSetting method.
message UpdateInstanceSettingRequest {
// The instance setting resource which replaces the resource on the server.
InstanceSetting setting = 1 [(google.api.field_behavior) = REQUIRED];
// The list of fields to update.
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = OPTIONAL];
}
// Request message for TestInstanceEmailSetting method.
message TestInstanceEmailSettingRequest {
// Optional. SMTP email settings to test. If omitted, the stored notification email setting is used.
InstanceSetting.NotificationSetting.EmailSetting email = 1 [(google.api.field_behavior) = OPTIONAL];
// Optional. Recipient email address. If omitted, the current user's email address is used.
string recipient_email = 2 [(google.api.field_behavior) = OPTIONAL];
}
// Request message for GetInstanceStats.
message GetInstanceStatsRequest {}
// Resource usage statistics for the instance.
message InstanceStats {
DatabaseStats database = 1;
// Recursive size of the data directory in bytes. -1 if unavailable.
int64 local_storage_bytes = 2;
// Server-side timestamp when the snapshot was generated.
google.protobuf.Timestamp generated_time = 4;
// Database size statistics.
message DatabaseStats {
// driver is one of "sqlite", "mysql", "postgres".
string driver = 1;
// size_bytes is the database size in bytes; -1 if unavailable.
int64 size_bytes = 2;
}
}
+656
View File
@@ -0,0 +1,656 @@
syntax = "proto3";
package memos.api.v1;
import "api/v1/attachment_service.proto";
import "api/v1/common.proto";
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
option go_package = "gen/api/v1";
service MemoService {
// CreateMemo creates a memo. The request body is a Memo; set its content
// (Markdown) and visibility (PRIVATE | PROTECTED | PUBLIC, default PRIVATE).
// The memo is owned by the authenticated user; requires authentication.
rpc CreateMemo(CreateMemoRequest) returns (Memo) {
option (google.api.http) = {
post: "/api/v1/memos"
body: "memo"
};
option (google.api.method_signature) = "memo";
}
// ListMemos lists memos with pagination and filter.
rpc ListMemos(ListMemosRequest) returns (ListMemosResponse) {
option (google.api.http) = {get: "/api/v1/memos"};
option (google.api.method_signature) = "";
}
// GetMemo gets a memo.
rpc GetMemo(GetMemoRequest) returns (Memo) {
option (google.api.http) = {get: "/api/v1/{name=memos/*}"};
option (google.api.method_signature) = "name";
}
// UpdateMemo updates a memo.
rpc UpdateMemo(UpdateMemoRequest) returns (Memo) {
option (google.api.http) = {
patch: "/api/v1/{memo.name=memos/*}"
body: "memo"
};
option (google.api.method_signature) = "memo,update_mask";
}
// DeleteMemo deletes a memo.
rpc DeleteMemo(DeleteMemoRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=memos/*}"};
option (google.api.method_signature) = "name";
}
// SetMemoAttachments replaces the full set of attachments on a memo with the
// provided list (not an append). Pass the complete desired set; an empty list
// clears all attachments. Idempotent.
rpc SetMemoAttachments(SetMemoAttachmentsRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
patch: "/api/v1/{name=memos/*}/attachments"
body: "*"
};
option (google.api.method_signature) = "name";
}
// ListMemoAttachments lists attachments for a memo.
rpc ListMemoAttachments(ListMemoAttachmentsRequest) returns (ListMemoAttachmentsResponse) {
option (google.api.http) = {get: "/api/v1/{name=memos/*}/attachments"};
option (google.api.method_signature) = "name";
}
// SetMemoRelations replaces the full set of relations on a memo with the
// provided list (not an append). Pass the complete desired set; an empty list
// clears all relations. Idempotent.
rpc SetMemoRelations(SetMemoRelationsRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {
patch: "/api/v1/{name=memos/*}/relations"
body: "*"
};
option (google.api.method_signature) = "name";
}
// ListMemoRelations lists relations for a memo.
rpc ListMemoRelations(ListMemoRelationsRequest) returns (ListMemoRelationsResponse) {
option (google.api.http) = {get: "/api/v1/{name=memos/*}/relations"};
option (google.api.method_signature) = "name";
}
// CreateMemoComment creates a comment for a memo.
rpc CreateMemoComment(CreateMemoCommentRequest) returns (Memo) {
option (google.api.http) = {
post: "/api/v1/{name=memos/*}/comments"
body: "comment"
};
option (google.api.method_signature) = "name,comment";
}
// ListMemoComments lists comments for a memo.
rpc ListMemoComments(ListMemoCommentsRequest) returns (ListMemoCommentsResponse) {
option (google.api.http) = {get: "/api/v1/{name=memos/*}/comments"};
option (google.api.method_signature) = "name";
}
// ListMemoReactions lists reactions for a memo.
rpc ListMemoReactions(ListMemoReactionsRequest) returns (ListMemoReactionsResponse) {
option (google.api.http) = {get: "/api/v1/{name=memos/*}/reactions"};
option (google.api.method_signature) = "name";
}
// UpsertMemoReaction adds or updates the authenticated user's reaction on a
// memo. The reaction's content_id is the memo's resource name (memos/{memo}).
rpc UpsertMemoReaction(UpsertMemoReactionRequest) returns (Reaction) {
option (google.api.http) = {
post: "/api/v1/{name=memos/*}/reactions"
body: "*"
};
option (google.api.method_signature) = "name";
}
// DeleteMemoReaction deletes a reaction for a memo.
rpc DeleteMemoReaction(DeleteMemoReactionRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=memos/*/reactions/*}"};
option (google.api.method_signature) = "name";
}
// CreateMemoShare creates a share link for a memo. Requires authentication as the memo creator.
rpc CreateMemoShare(CreateMemoShareRequest) returns (MemoShare) {
option (google.api.http) = {
post: "/api/v1/{parent=memos/*}/shares"
body: "memo_share"
};
option (google.api.method_signature) = "parent,memo_share";
}
// ListMemoShares lists all share links for a memo. Requires authentication as the memo creator.
rpc ListMemoShares(ListMemoSharesRequest) returns (ListMemoSharesResponse) {
option (google.api.http) = {get: "/api/v1/{parent=memos/*}/shares"};
option (google.api.method_signature) = "parent";
}
// DeleteMemoShare revokes a share link. Requires authentication as the memo creator.
rpc DeleteMemoShare(DeleteMemoShareRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=memos/*/shares/*}"};
option (google.api.method_signature) = "name";
}
// GetMemoByShare resolves a share token to its memo. No authentication required.
// Returns NOT_FOUND if the token is invalid or expired.
rpc GetMemoByShare(GetMemoByShareRequest) returns (Memo) {
option (google.api.http) = {get: "/api/v1/shares/{share_id}"};
}
// GetLinkMetadata gets metadata for a link.
rpc GetLinkMetadata(GetLinkMetadataRequest) returns (LinkMetadata) {
option (google.api.http) = {get: "/api/v1/memos/-/linkMetadata"};
}
// BatchGetLinkMetadata gets metadata for links.
rpc BatchGetLinkMetadata(BatchGetLinkMetadataRequest) returns (BatchGetLinkMetadataResponse) {
option (google.api.http) = {
post: "/api/v1/memos/-/linkMetadata:batchGet"
body: "*"
};
}
}
// Visibility controls who can read a memo.
enum Visibility {
VISIBILITY_UNSPECIFIED = 0;
// PRIVATE: only the creator can read the memo.
PRIVATE = 1;
// PROTECTED: signed-in users of the instance can read the memo.
PROTECTED = 2;
// PUBLIC: anyone, including anonymous visitors, can read the memo.
PUBLIC = 3;
}
message Reaction {
option (google.api.resource) = {
type: "memos.api.v1/Reaction"
pattern: "memos/{memo}/reactions/{reaction}"
name_field: "name"
singular: "reaction"
plural: "reactions"
};
// The resource name of the reaction.
// Format: memos/{memo}/reactions/{reaction}
string name = 1 [
(google.api.field_behavior) = OUTPUT_ONLY,
(google.api.field_behavior) = IDENTIFIER
];
// The resource name of the creator.
// Format: users/{user}
string creator = 2 [
(google.api.field_behavior) = OUTPUT_ONLY,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// The resource name of the content.
// For memo reactions, this should be the memo's resource name.
// Format: memos/{memo}
string content_id = 3 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Required. The type of reaction (e.g., "👍", "❤️", "😄").
string reaction_type = 4 [(google.api.field_behavior) = REQUIRED];
// Output only. The creation timestamp.
google.protobuf.Timestamp create_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
}
message Memo {
option (google.api.resource) = {
type: "memos.api.v1/Memo"
pattern: "memos/{memo}"
name_field: "name"
singular: "memo"
plural: "memos"
};
// The resource name of the memo.
// Format: memos/{memo}, memo is the user defined id or uuid.
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// The state of the memo.
State state = 2 [(google.api.field_behavior) = REQUIRED];
// The name of the creator.
// Format: users/{user}
string creator = 3 [
(google.api.field_behavior) = OUTPUT_ONLY,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// The creation timestamp.
// If not set on creation, the server will set it to the current time.
google.protobuf.Timestamp create_time = 4 [(google.api.field_behavior) = OPTIONAL];
// The last update timestamp.
// If not set on creation, the server will set it to the current time.
google.protobuf.Timestamp update_time = 5 [(google.api.field_behavior) = OPTIONAL];
reserved 6;
reserved "display_time";
// Required. The content of the memo in Markdown format.
string content = 7 [(google.api.field_behavior) = REQUIRED];
// The visibility of the memo.
// One of PRIVATE (creator only), PROTECTED (signed-in users), or
// PUBLIC (anyone). Defaults to PRIVATE on creation when unspecified.
Visibility visibility = 9 [(google.api.field_behavior) = REQUIRED];
// Output only. The tags extracted from the content.
repeated string tags = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
// Whether the memo is pinned.
bool pinned = 11 [(google.api.field_behavior) = OPTIONAL];
// Optional. The attachments of the memo.
repeated Attachment attachments = 12 [(google.api.field_behavior) = OPTIONAL];
// Optional. The relations of the memo.
repeated MemoRelation relations = 13 [(google.api.field_behavior) = OPTIONAL];
// Output only. The reactions to the memo.
repeated Reaction reactions = 14 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. The computed properties of the memo.
Property property = 15 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. The name of the parent memo.
// Format: memos/{memo}
optional string parent = 16 [
(google.api.field_behavior) = OUTPUT_ONLY,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Output only. The snippet of the memo content. Plain text only.
string snippet = 17 [(google.api.field_behavior) = OUTPUT_ONLY];
// Optional. The location of the memo.
optional Location location = 18 [(google.api.field_behavior) = OPTIONAL];
// Computed properties of a memo.
message Property {
bool has_link = 1;
bool has_task_list = 2;
bool has_code = 3;
bool has_incomplete_tasks = 4;
// The title extracted from the first H1 heading, if present.
string title = 5;
}
}
message Location {
// A placeholder text for the location.
string placeholder = 1 [(google.api.field_behavior) = OPTIONAL];
// The latitude of the location.
double latitude = 2 [(google.api.field_behavior) = OPTIONAL];
// The longitude of the location.
double longitude = 3 [(google.api.field_behavior) = OPTIONAL];
}
message CreateMemoRequest {
// Required. The memo to create.
Memo memo = 1 [(google.api.field_behavior) = REQUIRED];
// Optional. The memo ID to use for this memo.
// If empty, a unique ID will be generated.
string memo_id = 2 [(google.api.field_behavior) = OPTIONAL];
}
message ListMemosRequest {
// Optional. The maximum number of memos to return.
// The service may return fewer than this value.
// If unspecified, at most 50 memos will be returned.
// The maximum value is 1000; values above 1000 will be coerced to 1000.
int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token, received from a previous `ListMemos` call.
// Provide this to retrieve the subsequent page.
string page_token = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. The state of the memos to list.
// Default to `NORMAL`. Set to `ARCHIVED` to list archived memos.
State state = 3 [(google.api.field_behavior) = OPTIONAL];
// Optional. The order to sort results by.
// Default to "create_time desc".
// Supports comma-separated list of fields following AIP-132.
// Example: "pinned desc, create_time desc" or "update_time asc"
// Supported fields: pinned, create_time, update_time, name.
// Note: order_by uses create_time / update_time, while the filter
// expression uses created_ts / updated_ts for the same timestamps.
string order_by = 4 [(google.api.field_behavior) = OPTIONAL];
// Optional. A CEL expression to filter memos. Combine terms with && and ||.
// Available fields:
// content (string), creator (string, e.g. "users/1"),
// created_ts / updated_ts (timestamp), pinned (bool),
// visibility (string: PRIVATE | PROTECTED | PUBLIC),
// tags (list<string>; match with `"work" in tags`, not `tag == "work"`),
// has_task_list / has_link / has_code / has_incomplete_tasks (bool).
// Note: the time fields here are created_ts / updated_ts, which differ from
// the create_time / update_time names used by order_by.
// Examples:
// pinned == true && visibility == "PUBLIC"
// tags.exists(t, t == "urgent")
// content.contains("roadmap") && created_ts > now - duration("168h")
string filter = 5 [(google.api.field_behavior) = OPTIONAL];
// Optional. If true, show deleted memos in the response.
bool show_deleted = 6 [(google.api.field_behavior) = OPTIONAL];
}
message ListMemosResponse {
// The list of memos.
repeated Memo memos = 1;
// A token that can be sent as `page_token` to retrieve the next page.
// If this field is omitted, there are no subsequent pages.
string next_page_token = 2;
}
message GetMemoRequest {
// Required. The resource name of the memo.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
}
message UpdateMemoRequest {
// Required. The memo to update.
// The `name` field is required.
Memo memo = 1 [(google.api.field_behavior) = REQUIRED];
// Required. The list of fields to update.
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
}
message DeleteMemoRequest {
// Required. The resource name of the memo to delete.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Optional. If set to true, the memo will be deleted even if it has associated data.
bool force = 2 [(google.api.field_behavior) = OPTIONAL];
}
message SetMemoAttachmentsRequest {
// Required. The resource name of the memo.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Required. The attachments to set for the memo.
repeated Attachment attachments = 2 [(google.api.field_behavior) = REQUIRED];
}
message ListMemoAttachmentsRequest {
// Required. The resource name of the memo.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Optional. The maximum number of attachments to return.
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token for pagination.
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}
message ListMemoAttachmentsResponse {
// The list of attachments.
repeated Attachment attachments = 1;
// A token for the next page of results.
string next_page_token = 2;
}
message MemoRelation {
// The memo in the relation.
Memo memo = 1 [(google.api.field_behavior) = REQUIRED];
// The related memo.
Memo related_memo = 2 [(google.api.field_behavior) = REQUIRED];
// The type of the relation.
enum Type {
TYPE_UNSPECIFIED = 0;
REFERENCE = 1;
COMMENT = 2;
}
Type type = 3 [(google.api.field_behavior) = REQUIRED];
// Memo reference in relations.
message Memo {
// The resource name of the memo.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Output only. The snippet of the memo content. Plain text only.
string snippet = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
}
}
message SetMemoRelationsRequest {
// Required. The resource name of the memo.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Required. The relations to set for the memo.
repeated MemoRelation relations = 2 [(google.api.field_behavior) = REQUIRED];
}
message ListMemoRelationsRequest {
// Required. The resource name of the memo.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Optional. The maximum number of relations to return.
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token for pagination.
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}
message ListMemoRelationsResponse {
// The list of relations.
repeated MemoRelation relations = 1;
// A token for the next page of results.
string next_page_token = 2;
}
message CreateMemoCommentRequest {
// Required. The resource name of the memo.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Required. The comment to create.
Memo comment = 2 [(google.api.field_behavior) = REQUIRED];
// Optional. The comment ID to use.
string comment_id = 3 [(google.api.field_behavior) = OPTIONAL];
}
message ListMemoCommentsRequest {
// Required. The resource name of the memo.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Optional. The maximum number of comments to return.
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token for pagination.
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
// Optional. The order to sort results by.
string order_by = 4 [(google.api.field_behavior) = OPTIONAL];
}
message ListMemoCommentsResponse {
// The list of comment memos.
repeated Memo memos = 1;
// A token for the next page of results.
string next_page_token = 2;
}
message ListMemoReactionsRequest {
// Required. The resource name of the memo.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Optional. The maximum number of reactions to return.
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token for pagination.
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}
message ListMemoReactionsResponse {
// The list of reactions.
repeated Reaction reactions = 1;
// A token for the next page of results.
string next_page_token = 2;
}
message UpsertMemoReactionRequest {
// Required. The resource name of the memo.
// Format: memos/{memo}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Required. The reaction to upsert.
Reaction reaction = 2 [(google.api.field_behavior) = REQUIRED];
}
message DeleteMemoReactionRequest {
// Required. The resource name of the reaction to delete.
// Format: memos/{memo}/reactions/{reaction}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Reaction"}
];
}
// MemoShare is an access grant that permits read-only access to a memo via an opaque bearer token.
message MemoShare {
option (google.api.resource) = {
type: "memos.api.v1/MemoShare"
pattern: "memos/{memo}/shares/{share}"
singular: "share"
plural: "shares"
};
// The resource name of the share. Format: memos/{memo}/shares/{share}
// The {share} segment is the opaque token used in the share URL.
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// Output only. When this share link was created.
google.protobuf.Timestamp create_time = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
// Optional. When set, the share link stops working after this time.
// If unset, the link never expires.
optional google.protobuf.Timestamp expire_time = 3 [(google.api.field_behavior) = OPTIONAL];
}
message CreateMemoShareRequest {
// Required. The resource name of the memo to share.
// Format: memos/{memo}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
// Required. The share to create.
MemoShare memo_share = 2 [(google.api.field_behavior) = REQUIRED];
}
message ListMemoSharesRequest {
// Required. The resource name of the memo.
// Format: memos/{memo}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Memo"}
];
}
message ListMemoSharesResponse {
// The list of share links.
repeated MemoShare memo_shares = 1;
}
message DeleteMemoShareRequest {
// Required. The resource name of the share to delete.
// Format: memos/{memo}/shares/{share}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/MemoShare"}
];
}
message GetMemoByShareRequest {
// Required. The share token extracted from the share URL (/s/{share_id}).
string share_id = 1 [(google.api.field_behavior) = REQUIRED];
}
message GetLinkMetadataRequest {
// Required. The link URL.
string url = 1 [(google.api.field_behavior) = REQUIRED];
}
message BatchGetLinkMetadataRequest {
// Required. The link URLs.
repeated string urls = 1 [(google.api.field_behavior) = REQUIRED];
}
message BatchGetLinkMetadataResponse {
// The link metadata list, in the same order as the input URLs.
repeated LinkMetadata link_metadata = 1;
}
message LinkMetadata {
// The original link URL.
string url = 1;
// The link title.
string title = 2;
// The link description.
string description = 3;
// The link image URL.
string image = 4;
}
+127
View File
@@ -0,0 +1,127 @@
syntax = "proto3";
package memos.api.v1;
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
option go_package = "gen/api/v1";
service ShortcutService {
// ListShortcuts returns a user's saved shortcuts. Each shortcut is a named,
// reusable CEL filter (see Shortcut.filter); pass its filter string directly
// to the ListMemos `filter` argument to reuse a saved view.
rpc ListShortcuts(ListShortcutsRequest) returns (ListShortcutsResponse) {
option (google.api.http) = {get: "/api/v1/{parent=users/*}/shortcuts"};
option (google.api.method_signature) = "parent";
}
// GetShortcut gets a shortcut by name.
rpc GetShortcut(GetShortcutRequest) returns (Shortcut) {
option (google.api.http) = {get: "/api/v1/{name=users/*/shortcuts/*}"};
option (google.api.method_signature) = "name";
}
// CreateShortcut creates a new shortcut for a user.
rpc CreateShortcut(CreateShortcutRequest) returns (Shortcut) {
option (google.api.http) = {
post: "/api/v1/{parent=users/*}/shortcuts"
body: "shortcut"
};
option (google.api.method_signature) = "parent,shortcut";
}
// UpdateShortcut updates a shortcut for a user.
rpc UpdateShortcut(UpdateShortcutRequest) returns (Shortcut) {
option (google.api.http) = {
patch: "/api/v1/{shortcut.name=users/*/shortcuts/*}"
body: "shortcut"
};
option (google.api.method_signature) = "shortcut,update_mask";
}
// DeleteShortcut deletes a shortcut for a user.
rpc DeleteShortcut(DeleteShortcutRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=users/*/shortcuts/*}"};
option (google.api.method_signature) = "name";
}
}
message Shortcut {
option (google.api.resource) = {
type: "memos.api.v1/Shortcut"
pattern: "users/{username}/shortcuts/{shortcut}"
singular: "shortcut"
plural: "shortcuts"
};
// The resource name of the shortcut.
// Format: users/{username}/shortcuts/{shortcut}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// The title of the shortcut.
string title = 2 [(google.api.field_behavior) = REQUIRED];
// The CEL filter expression for the shortcut, using the same grammar as the
// ListMemos `filter` argument. Reuse it by passing this value to ListMemos.
string filter = 3 [(google.api.field_behavior) = OPTIONAL];
}
message ListShortcutsRequest {
// Required. The parent resource where shortcuts are listed.
// Format: users/{username}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {child_type: "memos.api.v1/Shortcut"}
];
}
message ListShortcutsResponse {
// The list of shortcuts.
repeated Shortcut shortcuts = 1;
}
message GetShortcutRequest {
// Required. The resource name of the shortcut to retrieve.
// Format: users/{username}/shortcuts/{shortcut}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Shortcut"}
];
}
message CreateShortcutRequest {
// Required. The parent resource where this shortcut will be created.
// Format: users/{username}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {child_type: "memos.api.v1/Shortcut"}
];
// Required. The shortcut to create.
Shortcut shortcut = 2 [(google.api.field_behavior) = REQUIRED];
// Optional. If set, validate the request, but do not actually create the shortcut.
bool validate_only = 3 [(google.api.field_behavior) = OPTIONAL];
}
message UpdateShortcutRequest {
// Required. The shortcut resource which replaces the resource on the server.
Shortcut shortcut = 1 [(google.api.field_behavior) = REQUIRED];
// Optional. The list of fields to update.
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = OPTIONAL];
}
message DeleteShortcutRequest {
// Required. The resource name of the shortcut to delete.
// Format: users/{username}/shortcuts/{shortcut}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Shortcut"}
];
}
+880
View File
@@ -0,0 +1,880 @@
syntax = "proto3";
package memos.api.v1;
import "api/v1/common.proto";
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "google/type/color.proto";
option go_package = "gen/api/v1";
service UserService {
// ListUsers returns a list of users.
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse) {
option (google.api.http) = {get: "/api/v1/users"};
}
// BatchGetUsers returns active users by usernames.
rpc BatchGetUsers(BatchGetUsersRequest) returns (BatchGetUsersResponse) {
option (google.api.http) = {
post: "/api/v1/users:batchGet"
body: "*"
};
}
// GetUser gets a user by username.
// Format: users/{username} (e.g., users/steven)
rpc GetUser(GetUserRequest) returns (User) {
option (google.api.http) = {get: "/api/v1/{name=users/*}"};
option (google.api.method_signature) = "name";
}
// CreateUser creates a new user.
rpc CreateUser(CreateUserRequest) returns (User) {
option (google.api.http) = {
post: "/api/v1/users"
body: "user"
};
option (google.api.method_signature) = "user";
}
// UpdateUser updates a user.
rpc UpdateUser(UpdateUserRequest) returns (User) {
option (google.api.http) = {
patch: "/api/v1/{user.name=users/*}"
body: "user"
};
option (google.api.method_signature) = "user,update_mask";
}
// DeleteUser deletes a user.
rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=users/*}"};
option (google.api.method_signature) = "name";
}
// ListAllUserStats returns statistics for all users.
rpc ListAllUserStats(ListAllUserStatsRequest) returns (ListAllUserStatsResponse) {
option (google.api.http) = {get: "/api/v1/users:stats"};
}
// GetUserStats returns statistics for a specific user.
rpc GetUserStats(GetUserStatsRequest) returns (UserStats) {
option (google.api.http) = {get: "/api/v1/{name=users/*}:getStats"};
option (google.api.method_signature) = "name";
}
// GetUserSetting returns the user setting.
rpc GetUserSetting(GetUserSettingRequest) returns (UserSetting) {
option (google.api.http) = {get: "/api/v1/{name=users/*/settings/*}"};
option (google.api.method_signature) = "name";
}
// UpdateUserSetting updates the user setting.
rpc UpdateUserSetting(UpdateUserSettingRequest) returns (UserSetting) {
option (google.api.http) = {
patch: "/api/v1/{setting.name=users/*/settings/*}"
body: "setting"
};
option (google.api.method_signature) = "setting,update_mask";
}
// ListUserSettings returns a list of user settings.
rpc ListUserSettings(ListUserSettingsRequest) returns (ListUserSettingsResponse) {
option (google.api.http) = {get: "/api/v1/{parent=users/*}/settings"};
option (google.api.method_signature) = "parent";
}
// ListLinkedIdentities returns a list of linked SSO identities for a user.
rpc ListLinkedIdentities(ListLinkedIdentitiesRequest) returns (ListLinkedIdentitiesResponse) {
option (google.api.http) = {get: "/api/v1/{parent=users/*}/linkedIdentities"};
option (google.api.method_signature) = "parent";
}
// CreateLinkedIdentity links an SSO identity to the authenticated user.
rpc CreateLinkedIdentity(CreateLinkedIdentityRequest) returns (LinkedIdentity) {
option (google.api.http) = {
post: "/api/v1/{parent=users/*}/linkedIdentities"
body: "*"
};
option (google.api.method_signature) = "parent,idp_name";
}
// GetLinkedIdentity gets a linked SSO identity for a user.
rpc GetLinkedIdentity(GetLinkedIdentityRequest) returns (LinkedIdentity) {
option (google.api.http) = {get: "/api/v1/{name=users/*/linkedIdentities/*}"};
option (google.api.method_signature) = "name";
}
// DeleteLinkedIdentity unlinks an SSO identity from a user.
rpc DeleteLinkedIdentity(DeleteLinkedIdentityRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=users/*/linkedIdentities/*}"};
option (google.api.method_signature) = "name";
}
// ListPersonalAccessTokens returns a list of Personal Access Tokens (PATs) for a user.
// PATs are long-lived tokens for API/script access, distinct from short-lived JWT access tokens.
rpc ListPersonalAccessTokens(ListPersonalAccessTokensRequest) returns (ListPersonalAccessTokensResponse) {
option (google.api.http) = {get: "/api/v1/{parent=users/*}/personalAccessTokens"};
option (google.api.method_signature) = "parent";
}
// CreatePersonalAccessToken creates a new Personal Access Token for a user.
// The token value is only returned once upon creation.
rpc CreatePersonalAccessToken(CreatePersonalAccessTokenRequest) returns (CreatePersonalAccessTokenResponse) {
option (google.api.http) = {
post: "/api/v1/{parent=users/*}/personalAccessTokens"
body: "*"
};
}
// DeletePersonalAccessToken deletes a Personal Access Token.
rpc DeletePersonalAccessToken(DeletePersonalAccessTokenRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=users/*/personalAccessTokens/*}"};
option (google.api.method_signature) = "name";
}
// ListUserWebhooks returns a list of webhooks for a user.
rpc ListUserWebhooks(ListUserWebhooksRequest) returns (ListUserWebhooksResponse) {
option (google.api.http) = {get: "/api/v1/{parent=users/*}/webhooks"};
option (google.api.method_signature) = "parent";
}
// CreateUserWebhook creates a new webhook for a user.
rpc CreateUserWebhook(CreateUserWebhookRequest) returns (UserWebhook) {
option (google.api.http) = {
post: "/api/v1/{parent=users/*}/webhooks"
body: "webhook"
};
option (google.api.method_signature) = "parent,webhook";
}
// UpdateUserWebhook updates an existing webhook for a user.
rpc UpdateUserWebhook(UpdateUserWebhookRequest) returns (UserWebhook) {
option (google.api.http) = {
patch: "/api/v1/{webhook.name=users/*/webhooks/*}"
body: "webhook"
};
option (google.api.method_signature) = "webhook,update_mask";
}
// DeleteUserWebhook deletes a webhook for a user.
rpc DeleteUserWebhook(DeleteUserWebhookRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=users/*/webhooks/*}"};
option (google.api.method_signature) = "name";
}
// GetUserWebhookSigningSecret returns the signing secret for a webhook.
// The secret is returned only through this explicit, owner-gated call; it is
// never included in List/Create/Update responses.
rpc GetUserWebhookSigningSecret(GetUserWebhookSigningSecretRequest) returns (GetUserWebhookSigningSecretResponse) {
option (google.api.http) = {get: "/api/v1/{name=users/*/webhooks/*}:getSigningSecret"};
option (google.api.method_signature) = "name";
}
// ListUserNotifications lists notifications for a user.
rpc ListUserNotifications(ListUserNotificationsRequest) returns (ListUserNotificationsResponse) {
option (google.api.http) = {get: "/api/v1/{parent=users/*}/notifications"};
option (google.api.method_signature) = "parent";
}
// UpdateUserNotification updates a notification.
rpc UpdateUserNotification(UpdateUserNotificationRequest) returns (UserNotification) {
option (google.api.http) = {
patch: "/api/v1/{notification.name=users/*/notifications/*}"
body: "notification"
};
option (google.api.method_signature) = "notification,update_mask";
}
// DeleteUserNotification deletes a notification.
rpc DeleteUserNotification(DeleteUserNotificationRequest) returns (google.protobuf.Empty) {
option (google.api.http) = {delete: "/api/v1/{name=users/*/notifications/*}"};
option (google.api.method_signature) = "name";
}
}
message User {
option (google.api.resource) = {
type: "memos.api.v1/User"
pattern: "users/{user}"
name_field: "name"
singular: "user"
plural: "users"
};
// The resource name of the user.
// Format: users/{user}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// The role of the user.
Role role = 2 [(google.api.field_behavior) = REQUIRED];
// Required. The unique username for login.
string username = 3 [(google.api.field_behavior) = REQUIRED];
// Optional. The email address of the user.
string email = 4 [(google.api.field_behavior) = OPTIONAL];
// Optional. The display name of the user.
string display_name = 5 [(google.api.field_behavior) = OPTIONAL];
// Optional. The avatar URL of the user.
string avatar_url = 6 [(google.api.field_behavior) = OPTIONAL];
// Optional. The description of the user.
string description = 7 [(google.api.field_behavior) = OPTIONAL];
// Input only. The password for the user.
string password = 8 [(google.api.field_behavior) = INPUT_ONLY];
// The state of the user.
State state = 9 [(google.api.field_behavior) = REQUIRED];
// Output only. The creation timestamp.
google.protobuf.Timestamp create_time = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
// Output only. The last update timestamp.
google.protobuf.Timestamp update_time = 11 [(google.api.field_behavior) = OUTPUT_ONLY];
// User role enumeration.
enum Role {
ROLE_UNSPECIFIED = 0;
// Admin role with system access.
ADMIN = 2;
// User role with limited access.
USER = 3;
}
}
message ListUsersRequest {
// Optional. The maximum number of users to return.
// The service may return fewer than this value.
// If unspecified, at most 50 users will be returned.
// The maximum value is 1000; values above 1000 will be coerced to 1000.
int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token, received from a previous `ListUsers` call.
// Provide this to retrieve the subsequent page.
string page_token = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. Filter to apply to the list results.
// Example: "username == 'steven'"
// Supported operators: ==
// Supported fields: username
string filter = 3 [(google.api.field_behavior) = OPTIONAL];
// Optional. If true, show deleted users in the response.
bool show_deleted = 4 [(google.api.field_behavior) = OPTIONAL];
}
message ListUsersResponse {
// The list of users.
repeated User users = 1;
// A token that can be sent as `page_token` to retrieve the next page.
// If this field is omitted, there are no subsequent pages.
string next_page_token = 2;
}
message BatchGetUsersRequest {
repeated string usernames = 1;
}
message BatchGetUsersResponse {
repeated User users = 1;
}
message GetUserRequest {
// Required. The resource name of the user.
// Format: users/{username}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// Optional. The fields to return in the response.
// If not specified, all fields are returned.
google.protobuf.FieldMask read_mask = 2 [(google.api.field_behavior) = OPTIONAL];
}
message CreateUserRequest {
// Required. The user to create.
User user = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.field_behavior) = INPUT_ONLY
];
// Optional. The user ID to use for this user.
// If empty, a unique ID will be generated.
// Must match the pattern [a-z0-9-]+
string user_id = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. If set, validate the request but don't actually create the user.
bool validate_only = 3 [(google.api.field_behavior) = OPTIONAL];
// Optional. An idempotency token that can be used to ensure that multiple
// requests to create a user have the same result.
string request_id = 4 [(google.api.field_behavior) = OPTIONAL];
}
message UpdateUserRequest {
// Required. The user to update.
User user = 1 [(google.api.field_behavior) = REQUIRED];
// Required. The list of fields to update.
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
// Optional. If set to true, allows updating sensitive fields.
bool allow_missing = 3 [(google.api.field_behavior) = OPTIONAL];
}
message DeleteUserRequest {
// Required. The resource name of the user to delete.
// Format: users/{user}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// Optional. If set to true, the user will be deleted even if they have associated data.
bool force = 2 [(google.api.field_behavior) = OPTIONAL];
}
// User statistics messages
message UserStats {
option (google.api.resource) = {
type: "memos.api.v1/UserStats"
pattern: "users/{user}"
singular: "userStats"
plural: "userStats"
};
// The resource name of the user whose stats these are.
// Format: users/{user}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
reserved 2;
reserved "memo_display_timestamps";
// The stats of memo types.
MemoTypeStats memo_type_stats = 3;
// The count of tags.
map<string, int32> tag_count = 4;
// The creation timestamps of the user's memos.
repeated google.protobuf.Timestamp memo_created_timestamps = 7;
// The latest update timestamps of the user's memos (one per memo,
// mirrors memo_created_timestamps). Used by the activity heatmap when
// the client's view is set to update_time basis.
repeated google.protobuf.Timestamp memo_updated_timestamps = 8;
// The pinned memos of the user.
repeated string pinned_memos = 5;
// Total memo count.
int32 total_memo_count = 6;
// Memo type statistics.
message MemoTypeStats {
int32 link_count = 1;
int32 code_count = 2;
int32 todo_count = 3;
int32 undo_count = 4;
}
}
message GetUserStatsRequest {
// Required. The resource name of the user.
// Format: users/{user}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
}
message ListAllUserStatsRequest {
// Optional. The state of memos to include. Defaults to NORMAL.
State state = 1 [(google.api.field_behavior) = OPTIONAL];
// Optional. Filter to apply to memo stats.
// Uses the same filter syntax as ListMemos.
string filter = 2 [(google.api.field_behavior) = OPTIONAL];
}
message ListAllUserStatsResponse {
// The list of user statistics.
repeated UserStats stats = 1;
}
// User settings message
message UserSetting {
option (google.api.resource) = {
type: "memos.api.v1/UserSetting"
pattern: "users/{username}/settings/{setting}"
singular: "userSetting"
plural: "userSettings"
};
// The name of the user setting.
// Format: users/{username}/settings/{setting}, {setting} is the key for the setting.
// For example, "users/steven/settings/GENERAL" for general settings.
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
oneof value {
GeneralSetting general_setting = 2;
WebhooksSetting webhooks_setting = 5;
TagsSetting tags_setting = 6;
}
// Enumeration of user setting keys.
enum Key {
KEY_UNSPECIFIED = 0;
// GENERAL is the key for general user settings.
GENERAL = 1;
// WEBHOOKS is the key for user webhooks.
WEBHOOKS = 4;
// TAGS is the key for per-user tag metadata.
TAGS = 5;
}
// General user settings configuration.
message GeneralSetting {
// The preferred locale of the user.
string locale = 1 [(google.api.field_behavior) = OPTIONAL];
// The default visibility of the memo.
string memo_visibility = 3 [(google.api.field_behavior) = OPTIONAL];
// The preferred theme of the user.
// This references a CSS file in the web/public/themes/ directory.
// If not set, the default theme will be used.
string theme = 4 [(google.api.field_behavior) = OPTIONAL];
}
// Tag metadata for user-specific display rules.
message TagMetadata {
// Optional background color for the tag label.
// When unset, the default tag color is used.
google.type.Color background_color = 1 [(google.api.field_behavior) = OPTIONAL];
// Whether memos with this tag should have their content blurred.
bool blur_content = 2 [(google.api.field_behavior) = OPTIONAL];
}
// User-specific tag metadata.
message TagsSetting {
// Map of tag name pattern to tag metadata.
// Each key is treated as an anchored regular expression (^pattern$).
map<string, TagMetadata> tags = 1 [(google.api.field_behavior) = OPTIONAL];
}
// User webhooks configuration.
message WebhooksSetting {
// List of user webhooks.
repeated UserWebhook webhooks = 1;
}
}
message GetUserSettingRequest {
// Required. The resource name of the user setting.
// Format: users/{user}/settings/{setting}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/UserSetting"}
];
}
message UpdateUserSettingRequest {
// Required. The user setting to update.
UserSetting setting = 1 [(google.api.field_behavior) = REQUIRED];
// Required. The list of fields to update.
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
}
// Request message for ListUserSettings method.
message ListUserSettingsRequest {
// Required. The parent resource whose settings will be listed.
// Format: users/{user}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// Optional. The maximum number of settings to return.
// The service may return fewer than this value.
// If unspecified, at most 50 settings will be returned.
// The maximum value is 1000; values above 1000 will be coerced to 1000.
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token, received from a previous `ListUserSettings` call.
// Provide this to retrieve the subsequent page.
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}
// Response message for ListUserSettings method.
message ListUserSettingsResponse {
// The list of user settings.
repeated UserSetting settings = 1;
// A token that can be sent as `page_token` to retrieve the next page.
// If this field is omitted, there are no subsequent pages.
string next_page_token = 2;
}
// LinkedIdentity represents an SSO identity linked to a user account.
message LinkedIdentity {
option (google.api.resource) = {
type: "memos.api.v1/LinkedIdentity"
pattern: "users/{user}/linkedIdentities/{linked_identity}"
singular: "linkedIdentity"
plural: "linkedIdentities"
};
// The resource name of the linked identity.
// Format: users/{user}/linkedIdentities/{linked_identity}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// The resource name of the identity provider.
// Format: identity-providers/{uid}
string idp_name = 2 [
(google.api.field_behavior) = OUTPUT_ONLY,
(google.api.resource_reference) = {type: "memos.api.v1/IdentityProvider"}
];
// The external user identifier from the identity provider.
string extern_uid = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
}
message ListLinkedIdentitiesRequest {
// Required. The parent resource whose linked identities will be listed.
// Format: users/{user}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
}
message ListLinkedIdentitiesResponse {
// The list of linked identities.
repeated LinkedIdentity linked_identities = 1;
}
message CreateLinkedIdentityRequest {
// Required. The parent user who owns the linked identity.
// Format: users/{user}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// Required. The identity provider to link.
// Format: identity-providers/{uid}
string idp_name = 2 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/IdentityProvider"}
];
// Required. The authorization code from the identity provider.
string code = 3 [(google.api.field_behavior) = REQUIRED];
// Required. The redirect URI used in the OAuth flow.
string redirect_uri = 4 [(google.api.field_behavior) = REQUIRED];
// Optional. The PKCE code verifier used in the OAuth flow.
string code_verifier = 5 [(google.api.field_behavior) = OPTIONAL];
}
message GetLinkedIdentityRequest {
// Required. The resource name of the linked identity to get.
// Format: users/{user}/linkedIdentities/{linked_identity}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/LinkedIdentity"}
];
}
message DeleteLinkedIdentityRequest {
// Required. The resource name of the linked identity to delete.
// Format: users/{user}/linkedIdentities/{linked_identity}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/LinkedIdentity"}
];
}
// PersonalAccessToken represents a long-lived token for API/script access.
// PATs are distinct from short-lived JWT access tokens used for session authentication.
message PersonalAccessToken {
option (google.api.resource) = {
type: "memos.api.v1/PersonalAccessToken"
pattern: "users/{user}/personalAccessTokens/{personal_access_token}"
singular: "personalAccessToken"
plural: "personalAccessTokens"
};
// The resource name of the personal access token.
// Format: users/{user}/personalAccessTokens/{personal_access_token}
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// The description of the token.
string description = 2 [(google.api.field_behavior) = OPTIONAL];
// Output only. The creation timestamp.
google.protobuf.Timestamp created_at = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
// Optional. The expiration timestamp.
google.protobuf.Timestamp expires_at = 4 [(google.api.field_behavior) = OPTIONAL];
// Output only. The last used timestamp.
google.protobuf.Timestamp last_used_at = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
}
message ListPersonalAccessTokensRequest {
// Required. The parent resource whose personal access tokens will be listed.
// Format: users/{user}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// Optional. The maximum number of tokens to return.
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. A page token for pagination.
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}
message ListPersonalAccessTokensResponse {
// The list of personal access tokens.
repeated PersonalAccessToken personal_access_tokens = 1;
// A token for the next page of results.
string next_page_token = 2;
}
message CreatePersonalAccessTokenRequest {
// Required. The parent resource where this token will be created.
// Format: users/{user}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// Optional. Description of the personal access token.
string description = 2 [(google.api.field_behavior) = OPTIONAL];
// Optional. Expiration duration in days (0 = never expires).
int32 expires_in_days = 3 [(google.api.field_behavior) = OPTIONAL];
}
message CreatePersonalAccessTokenResponse {
// The personal access token metadata.
PersonalAccessToken personal_access_token = 1;
// The actual token value - only returned on creation.
// This is the only time the token value will be visible.
string token = 2;
}
message DeletePersonalAccessTokenRequest {
// Required. The resource name of the personal access token to delete.
// Format: users/{user}/personalAccessTokens/{personal_access_token}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/PersonalAccessToken"}
];
}
// UserWebhook represents a webhook owned by a user.
message UserWebhook {
// The name of the webhook.
// Format: users/{user}/webhooks/{webhook}
string name = 1;
// The URL to send the webhook to.
string url = 2;
// Optional. Human-readable name for the webhook.
string display_name = 3;
// The creation time of the webhook.
google.protobuf.Timestamp create_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
// The last update time of the webhook.
google.protobuf.Timestamp update_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
// Optional. Signing secret used to HMAC-SHA256 sign the webhook request body.
// This field is input-only; it is never returned in responses.
string signing_secret = 6 [(google.api.field_behavior) = INPUT_ONLY];
// Whether a signing secret is configured for this webhook.
bool signing_secret_set = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
}
message ListUserWebhooksRequest {
// The parent user resource.
// Format: users/{user}
string parent = 1 [(google.api.field_behavior) = REQUIRED];
}
message ListUserWebhooksResponse {
// The list of webhooks.
repeated UserWebhook webhooks = 1;
}
message CreateUserWebhookRequest {
// The parent user resource.
// Format: users/{user}
string parent = 1 [(google.api.field_behavior) = REQUIRED];
// The webhook to create.
UserWebhook webhook = 2 [(google.api.field_behavior) = REQUIRED];
}
message UpdateUserWebhookRequest {
// The webhook to update.
UserWebhook webhook = 1 [(google.api.field_behavior) = REQUIRED];
// The list of fields to update.
google.protobuf.FieldMask update_mask = 2;
}
message DeleteUserWebhookRequest {
// The name of the webhook to delete.
// Format: users/{user}/webhooks/{webhook}
string name = 1 [(google.api.field_behavior) = REQUIRED];
}
message GetUserWebhookSigningSecretRequest {
// The name of the webhook whose signing secret to reveal.
// Format: users/{user}/webhooks/{webhook}
string name = 1 [(google.api.field_behavior) = REQUIRED];
}
message GetUserWebhookSigningSecretResponse {
// The signing secret, in the Standard Webhooks "whsec_<base64>" form.
string signing_secret = 1;
}
message UserNotification {
option (google.api.resource) = {
type: "memos.api.v1/UserNotification"
pattern: "users/{user}/notifications/{notification}"
name_field: "name"
singular: "notification"
plural: "notifications"
};
// The resource name of the notification.
// Format: users/{user}/notifications/{notification}
string name = 1 [
(google.api.field_behavior) = OUTPUT_ONLY,
(google.api.field_behavior) = IDENTIFIER
];
// The sender of the notification.
// Format: users/{user}
string sender = 2 [
(google.api.field_behavior) = OUTPUT_ONLY,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
// The sender user details.
User sender_user = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
// The status of the notification.
Status status = 3 [(google.api.field_behavior) = OPTIONAL];
// The creation timestamp.
google.protobuf.Timestamp create_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
// The type of the notification.
Type type = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
oneof payload {
MemoCommentPayload memo_comment = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
MemoMentionPayload memo_mention = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
}
message MemoCommentPayload {
// The memo name of comment.
// Format: memos/{memo}
string memo = 1;
// The name of related memo.
// Format: memos/{memo}
string related_memo = 2;
// Preview text of the comment memo.
string memo_snippet = 3;
// Preview text of the related memo.
string related_memo_snippet = 4;
}
message MemoMentionPayload {
// The memo that contains the mention.
// Format: memos/{memo}
string memo = 1;
// The related parent memo when the mention was created in a comment.
// Format: memos/{memo}
string related_memo = 2;
// Preview text of the memo that contains the mention.
string memo_snippet = 3;
// Preview text of the related parent memo.
string related_memo_snippet = 4;
}
enum Status {
STATUS_UNSPECIFIED = 0;
UNREAD = 1;
ARCHIVED = 2;
}
enum Type {
TYPE_UNSPECIFIED = 0;
MEMO_COMMENT = 1;
MEMO_MENTION = 2;
}
}
message ListUserNotificationsRequest {
// The parent user resource.
// Format: users/{user}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/User"}
];
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
string filter = 4 [(google.api.field_behavior) = OPTIONAL];
}
message ListUserNotificationsResponse {
repeated UserNotification notifications = 1;
string next_page_token = 2;
}
message UpdateUserNotificationRequest {
UserNotification notification = 1 [(google.api.field_behavior) = REQUIRED];
google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
}
message DeleteUserNotificationRequest {
// Format: users/{user}/notifications/{notification}
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/UserNotification"}
];
}