// capability.proto — guest→host capability calls (WO-WZ-001). // // Each CoreServices interface (core/plugin/deps.go) becomes a host-function // family; every interface method gets one request/response message pair // here, mirroring the Go signature 1:1. UUIDs travel as canonical strings; // map[string]any / []byte-JSON values travel as JSON bytes. // // Calls cross via the generic HostCallRequest/HostCallResponse envelope; the // method string selects the pair (e.g. "content.get_author_profile" → // ContentGetAuthorProfileRequest/Response). Full method table in // core/docs/wasm-abi.md. // // Not represented here by design: // - CoreServices.Pool → db.proto (the DB driver messages) // - CoreServices.Interceptors → host-side only (never crosses) // - CoreServices.AppURL/MediaPath → LoadRequest.host_config (invoke.proto) // - CoreServices.CoreServiceBindings → manifest core_service_bindings // - RAGService.RegisterContentFetcher → manifest rag_content_fetcher_types // + the RAG_FETCH hook (callback inversion) // - ai.ToolDefinition.Handler → host→guest tool execution is a runtime-WO // concern (flagged in core/docs/wasm-abi.md) syntax = "proto3"; package abi.v1; import "google/protobuf/timestamp.proto"; import "v1/invoke.proto"; option go_package = "git.dev.alexdunmow.com/block/core/abi/v1;abiv1"; // HostCallRequest is the generic guest→host capability envelope. message HostCallRequest { // Capability method, "." (e.g. "crypto.encrypt_secret"). string method = 1; // Serialized family request message. bytes payload = 2; } // HostCallResponse is the generic host→guest capability return envelope. message HostCallResponse { // Serialized family response message; empty when error is set. bytes payload = 1; // Set when the capability call failed; the guest SDK surfaces it as a // normal Go error. AbiError error = 2; } // --- content.* (content.Content) --- message ContentGetAuthorProfileRequest { string id = 1; // UUID } message ContentGetAuthorProfileResponse { AuthorProfile author = 1; } // AuthorProfile mirrors content.AuthorProfile. message AuthorProfile { string id = 1; // UUID string name = 2; string slug = 3; string bio = 4; string avatar_url = 5; string website = 6; map social_links = 7; } message ContentGetPageRequest { string slug = 1; } message ContentGetPageResponse { PageInfo page = 1; } // PageInfo mirrors content.PageInfo. message PageInfo { string id = 1; // UUID string slug = 2; string title = 3; } message ContentGetPostRequest { string slug = 1; } message ContentGetPostResponse { PostInfo post = 1; } // PostInfo mirrors content.PostInfo. message PostInfo { string id = 1; // UUID string slug = 2; string title = 3; string excerpt = 4; string featured_image_url = 5; string author_id = 6; // UUID } message ContentSlugifyRequest { string text = 1; } message ContentSlugifyResponse { string slug = 1; } message ContentBlockNoteToHtmlRequest { // JSON encoding of the BlockNote document map. bytes doc_json = 1; } message ContentBlockNoteToHtmlResponse { string html = 1; } message ContentGenerateExcerptRequest { string html = 1; int32 max_len = 2; } message ContentGenerateExcerptResponse { string excerpt = 1; } message ContentStripHtmlRequest { string html = 1; } message ContentStripHtmlResponse { string text = 1; } // --- settings.* (settings.Settings) + settings.update (settings.Updater) --- message SettingsGetSiteSettingsRequest {} message SettingsGetSiteSettingsResponse { // JSON encoding of the site settings map. bytes settings_json = 1; } message SettingsGetPluginSettingsRequest { string plugin_name = 1; } message SettingsGetPluginSettingsResponse { // JSON encoding of the plugin settings map. bytes settings_json = 1; } message SettingsUpdateSiteSettingRequest { string key = 1; // JSON encoding of the value. bytes value_json = 2; } message SettingsUpdateSiteSettingResponse {} // --- gating.* (gating.Gating) --- message GatingGetSubscriberTierLevelRequest { string user_id = 1; // UUID } message GatingGetSubscriberTierLevelResponse { int32 level = 1; } message GatingEvaluateAccessRequest { int32 user_tier_level = 1; // Absent rule means "no rule" (access granted). AccessRule rule = 2; } message GatingEvaluateAccessResponse { AccessResult result = 1; } // AccessRule mirrors gating.AccessRule. message AccessRule { int32 min_tier_level = 1; string override_tier_id = 2; string teaser_mode = 3; // "hard", "soft", "none" int32 teaser_percent = 4; } // AccessResult mirrors gating.AccessResult. message AccessResult { bool has_access = 1; string teaser_mode = 2; int32 teaser_percent = 3; int32 required_level = 4; } // --- crypto.* (crypto.Crypto) --- message CryptoEncryptSecretRequest { string plaintext = 1; } message CryptoEncryptSecretResponse { string ciphertext = 1; } message CryptoDecryptSecretRequest { string ciphertext = 1; } message CryptoDecryptSecretResponse { string plaintext = 1; } // --- menus.* (menus.Menus) --- message MenusGetMenuByNameRequest { string name = 1; } message MenusGetMenuByNameResponse { Menu menu = 1; } // Menu mirrors menus.Menu. message Menu { string id = 1; // UUID string name = 2; } message MenusGetMenuItemsRequest { string menu_id = 1; // UUID } message MenusGetMenuItemsResponse { repeated MenuItem items = 1; } // MenuItem mirrors menus.MenuItem. message MenuItem { string id = 1; // UUID string menu_id = 2; // UUID string label = 3; string url = 4; string page_slug = 5; optional string parent_id = 6; // UUID; unset mirrors nil *uuid.UUID int32 sort_order = 7; bool open_in_new_tab = 8; string css_class = 9; string item_type = 10; string icon = 11; } // --- datasources.* (datasources.Datasources) --- message DatasourcesResolveBucketRequest { string bucket_id = 1; // UUID } message DatasourcesResolveBucketResponse { DatasourceResult result = 1; } message DatasourcesResolveBucketByKeyRequest { string bucket_key = 1; } message DatasourcesResolveBucketByKeyResponse { DatasourceResult result = 1; } // DatasourceResult mirrors datasources.Result ([]any / map[string]any as // JSON bytes). message DatasourceResult { // JSON array of items. bytes items_json = 1; int32 total = 2; // JSON object; empty when absent. bytes meta_json = 3; } // --- users.* (auth.PublicUsers) --- message UsersGetByUsernameRequest { string username = 1; } message UsersGetByUsernameResponse { PublicUserProfile user = 1; } message UsersGetByIdRequest { string id = 1; // UUID } message UsersGetByIdResponse { PublicUserProfile user = 1; } // PublicUserProfile mirrors auth.PublicUserProfile. message PublicUserProfile { string id = 1; // UUID string email = 2; string username = 3; string display_name = 4; string avatar_url = 5; string bio = 6; bool email_verified = 7; string role = 8; } // --- subscriptions.* (subscriptions.Subscriptions) --- message SubscriptionsGetUserTierLevelRequest { string user_id = 1; // UUID } message SubscriptionsGetUserTierLevelResponse { TierLevel tier_level = 1; } // TierLevel mirrors subscriptions.TierLevel. message TierLevel { int32 level = 1; // JSON feature payload. bytes features = 2; } message SubscriptionsGetTierBySlugRequest { string slug = 1; } message SubscriptionsGetTierBySlugResponse { Tier tier = 1; } // Tier mirrors subscriptions.Tier. message Tier { string id = 1; // UUID string name = 2; string slug = 3; int32 level = 4; string description = 5; // JSON feature payload. bytes features = 6; bool is_default = 7; int32 position = 8; } message SubscriptionsListTiersRequest {} message SubscriptionsListTiersResponse { repeated Tier tiers = 1; } message SubscriptionsListActivePlansRequest { string tier_id = 1; // UUID } message SubscriptionsListActivePlansResponse { repeated Plan plans = 1; } // Plan mirrors subscriptions.Plan. message Plan { string id = 1; // UUID string tier_id = 2; // UUID string billing_interval = 3; int32 amount = 4; string currency = 5; bool is_active = 6; google.protobuf.Timestamp created_at = 7; } // --- media.deposit (plugin.Media) --- // MediaDepositRequest mirrors plugin.MediaDeposit. message MediaDepositRequest { // Optional deterministic media row ID (UUID); empty = host generates one. string id = 1; string filename = 2; bytes data = 3; string alt_text = 4; string folder = 5; string source = 6; } // MediaDepositResponse mirrors plugin.MediaResult. message MediaDepositResponse { string id = 1; // UUID // Ready-to-use reference ("media:"). string ref = 2; bool created = 3; } // --- email.send (plugin.EmailSender) --- message EmailSendRequest { string to = 1; string subject = 2; string body = 3; } message EmailSendResponse {} // --- ai.text_call (CoreServices.AITextCall) --- message AiTextCallRequest { string task_key = 1; string system_prompt = 2; string user_message = 3; } message AiTextCallResponse { string text = 1; } // --- ai.tools.* (ai.ToolRegistry) --- // AiToolRegisterRequest mirrors ai.ToolDefinition (minus Handler, which // stays guest-side; execution direction is a runtime-WO concern). message AiToolRegisterRequest { string slug = 1; string name = 2; string description = 3; // JSON encoding of the parameter schema map. bytes parameter_schema_json = 4; } message AiToolRegisterResponse {} // --- bridge.* (plugin.PluginBridge) --- // // The bridge shares in-process Go values today; across sandboxes only the // registration/lookup surface serializes. Typed cross-plugin calls need a // runtime design (see core/docs/wasm-abi.md, open items). message BridgeRegisterServiceRequest { string plugin_name = 1; string service_name = 2; } message BridgeRegisterServiceResponse {} message BridgeGetServiceRequest { string plugin_name = 1; string service_name = 2; } message BridgeGetServiceResponse { bool available = 1; } // --- jobs.submit (plugin.JobRunner) --- message JobsSubmitRequest { string job_type = 1; // JSON job configuration. bytes config_json = 2; } message JobsSubmitResponse {} // --- embeddings.* (plugin.EmbeddingService) --- message EmbeddingsGenerateEmbeddingRequest { string text = 1; } message EmbeddingsGenerateEmbeddingResponse { repeated float embedding = 1; } message EmbeddingsEmbedContentRequest { string source_type = 1; string source_id = 2; // UUID string text = 3; } message EmbeddingsEmbedContentResponse { bool embedded = 1; } message EmbeddingsIsAvailableRequest {} message EmbeddingsIsAvailableResponse { bool available = 1; } // --- rag.* (plugin.RAGService) --- message RagQueryRequest { string query = 1; int32 limit = 2; } message RagQueryResponse { repeated RagResult results = 1; } // RagResult mirrors plugin.RAGResult. message RagResult { string content = 1; double score = 2; map metadata = 3; } message RagOnContentChangedRequest { string content_type = 1; string content_id = 2; // UUID } message RagOnContentChangedResponse {} // --- reviews.* (plugin.ReviewSubmitter) --- // ReviewsSubmitReviewRequest mirrors plugin.SubmitReviewParams. message ReviewsSubmitReviewRequest { string table_id = 1; // UUID string row_id = 2; // UUID int32 overall_rating = 3; string review_text = 4; // JSON encoding of the per-criterion ratings map. bytes ratings_json = 5; repeated string photos = 6; } message ReviewsSubmitReviewResponse { string review_id = 1; } // --- badges.refresh (plugin.BadgeRefresher) --- message BadgesRefreshBadgesRequest { string table_id = 1; // UUID string row_id = 2; // UUID } message BadgesRefreshBadgesResponse {}